2010-02-02 86 views

回答

3

這是一個很好的問題,雖然類似的問題已經在這裏被問過很多次。我對OSX方面很感興趣,因爲我試圖在自己的系統上加快速度。 (也許你應該添加OSX標籤)

想想 fprintf()在OSX上是線程安全的。我的第一個原因是,達爾文人正朝着這個方向前進,證明他們選擇放棄舊式全球「errno」而轉而使用errno()函數。對於文檔,只需按照'/usr/include/errno.h'。沒有這些,沒有任何libc的東西會是線程安全的。然而,使用errno()函數並不能證明fprintf()的任何內容。這只是一個開始。我相信每個人都知道至少有一種情況蘋果沒有一個好主意。

我相信fprintf()的'線程安全性'的另一個原因是source code,它應該是'真實的',至少在Apple關閉(部分/全部)OSX的10.6之前。掃描該代碼以獲得「MT-Safe」,並且您將看到一個CLAIM,'vfprintf()'的非本地版本是線程安全的。再次,這沒有任何證據。但它是一種你想要的文檔形式。

我相信fprintf()是線程安全的最終原因是測試用例。這也沒有證明任何東西。也許它證明了緩衝區空間是線程安全的。好吧,這是寫一個有趣的小程序的藉口。其實,我沒有寫。我在網上找到了一個骨架,並對其進行了修改「FLUSH_BUFFER」定義允許您更清楚地看到發生了什麼。如果這個宏沒有定義,你會得到'排序'緩衝區測試(同樣的文本沒有一些行終止符)。我找不出一種方法來安排更有意義的線程衝突。

我猜你可能會寫入多個文件。寫入單個文件可能是一個更好的測試。附加的程序不是一個明確的測試。儘管可以擴展,但我不確定任何程序是否可以確定。底線:也許你應該只是MUTEX你的電話fprintf()。

// artificial test for thread safety of fprintf() 
// define FLUSH_BUFFER to get a good picture of what's happening, un-def for a buffer test 
// the 'pretty print' (FLUSH_BUFFER) output relies on a mono-spaced font 
// a writeable file name on the command line will send output to that file 
// 

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

#define FLUSH_BUFFER 

#define NTHREAD  5 
#define ITERATIONS 3 

const char DOTS[] = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "; 
FILE *outFile; 

void *PrintHello(void *threadid) { 
    long tid; 

    tid = (long)threadid; 
    for (int i=1; i<=ITERATIONS; i++) { 
     long delay = (NTHREAD-tid) * 100000 + (ITERATIONS-i+1) * 10000; 
#ifdef FLUSH_BUFFER 
     fprintf(outFile, "%*sStart thread %d iteration %d\n", (tid+1)*4, " ", tid, i); 
     usleep(delay); 
     fprintf(outFile, "%*sFinish thread %d iteration %d %*.*sw/delay %d\n", 
       (tid+1)*4, " ", tid, i, (NTHREAD-tid+1)*4, (NTHREAD-tid+1)*4, DOTS, delay); 
#else 
     fprintf(outFile, "Start thread %d iteration %d ", tid, i); 
     usleep(delay); 
     fprintf(outFile, "Finish thread %d iteration %d w/delay %d\n", tid, i, delay); 
#endif 
    } 
    pthread_exit(NULL); 
} 

int main (int argc, char *argv[]) { 
    pthread_t threads[NTHREAD]; 
    char errStr[100]; 
    int rc; 
    long t; 

    if(argc > 1) { 
     if(! (outFile = fopen(argv[1], "w"))) { 
      perror(argv[1]); 
      exit(1); 
     } 
    } else 
     outFile = stdout; 

    for(t=0; t<NTHREAD; t++) { 
     fprintf(outFile, "In main: creating thread %ld\n", t); 
     if(rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t)) { 
      sprintf(errStr, "ERROR; pthread_create() returned %d", rc); 
      perror(errStr); 
      exit(2); 
     } 
    } 
    pthread_exit(NULL); 
}