2010-02-02 26 views

Trả lời

3

Đây là một câu hỏi hay, mặc dù nhiều câu hỏi tương tự đã được hỏi ở đây nhiều lần. Tôi đã quan tâm đến khía cạnh OSX bởi vì tôi đang cố gắng tăng tốc độ trên hệ thống đó. (có thể bạn nên thêm thẻ OSX)

I THINK fprintf() là luồng an toàn trên OSX. Lý do đầu tiên của tôi cho điều này là người dân Darwin đã đi theo hướng đó bằng chứng là sự lựa chọn của họ để thả trường toàn cầu cũ 'errno' có lợi cho hàm errno(). Đối với tài liệu, chỉ cần làm theo '/usr/include/errno.h'. Nếu không có điều đó, không ai trong số các công cụ libc sẽ được thread an toàn. Tuy nhiên, việc sử dụng hàm errno() không chứng minh được gì về fprintf(). Nó chỉ là một sự khởi đầu. Tôi chắc rằng mọi người đều biết ít nhất một tình huống mà Apple đã không thực hiện với một ý tưởng tốt.

Một lý do khác mà tôi tin vào 'thread-safety' của fprintf() là source code, được cho là 'điều thực', ít nhất cho đến 10.6 khi Apple đóng (part/all) của OSX. Quét mã đó cho "MT-Safe" và bạn sẽ thấy CLAIM rằng phiên bản không phải miền địa phương của 'vfprintf()' là chuỗi an toàn. Một lần nữa, điều đó không chứng minh bất cứ điều gì. Tuy nhiên, nó là một hình thức tài liệu, mà bạn muốn.

Lý do cuối cùng của tôi để tin rằng fprintf() là an toàn chỉ là một trường hợp thử nghiệm. Điều này cũng không chứng minh được gì nhiều. Có lẽ nó chứng minh không gian bộ đệm là thread an toàn. OK, đó là một cái cớ để viết một chương trình nhỏ cho vui. Thực ra, tôi không viết nó. Tôi tìm thấy một bộ xương trực tuyến, và sửa đổi nó. Định nghĩa "FLUSH_BUFFER" cho phép bạn xem rõ hơn những gì đang xảy ra. Nếu macro đó không được xác định, bạn sẽ nhận được kiểm tra bộ đệm 'sắp xếp' (cùng một văn bản mà không có một số thuật ngữ dòng). Tôi không thể tìm ra cách để sắp xếp một va chạm có ý nghĩa hơn của các chủ đề.

Tôi đoán bạn có thể đang viết nhiều tệp. Việc ghi vào một tệp có thể là một thử nghiệm tốt hơn. Chương trình đính kèm không phải là một thử nghiệm cuối cùng. Mặc dù nó có thể được mở rộng, tôi không chắc chắn bất kỳ chương trình thực sự có thể được dứt khoát. Tóm lại: có thể bạn chỉ cần MUTEX các cuộc gọi của bạn để 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); 
} 
5

Đặc tả chủ đề POSIX (AKA Pthreads), mà OS X tuân thủ, yêu cầu các chức năng stdio là an toàn chỉ. Nó cũng cung cấp các chức năng flockfilefunlockfile để đảm bảo rằng các chủ đề khác không thể xen kẽ I/O trên một FILE * trong khi nó bị khóa.

Xem http://pubs.opengroup.org/onlinepubs/007908799/xsh/threads.html, cụ thể trong phần có tiêu đề "An toàn chủ đề".

Các vấn đề liên quan