2010-02-02 7 views

Antwort

3

Das war eine gute Frage, obwohl ähnliche Fragen hier oft gestellt wurden. Ich war am OSX-Aspekt interessiert, weil ich mich selbst auf dieses System einstellen wollte. (vielleicht sollten Sie das OSX-Tag hinzufügen)

I THINK fprintf() ist threadsicher auf OSX. Mein erster Grund dafür ist, dass die Darwin-Leute in diese Richtung gingen, was sich in ihrer Entscheidung widerspiegelt, das globale "Errno" der alten Schule zugunsten der Funktion errno() fallen zu lassen. Folgen Sie zur Dokumentation einfach '/usr/include/errno.h'. Ohne das wäre keines der libc-Dinge threadsicher. Die Verwendung der Funktion errno() beweist jedoch nichts über fprintf(). Es ist nur ein Anfang. Ich bin sicher, dass jeder von mindestens einer Situation weiß, in der Apple keine gute Idee hatte. Ein weiterer Grund, warum ich an die 'thread-safety' von fprintf glaube, ist die source code, die angeblich "das wahre Ding" sein soll, zumindest bis 10.6, als Apple (teilweise/vollständig) OSX geschlossen hat. Scannen Sie den Code für "MT-Safe" und Sie werden sehen, CLAIM, dass die nicht-locale Version von "vfprintf()" threadsicher ist. Auch das beweist nichts. Aber es ist eine Form der Dokumentation, die Sie wollten.

Mein letzter Grund zu glauben, dass fprintf() Thread-sicher ist, war ein Testfall. Dies beweist auch nicht viel von irgendetwas. Vielleicht beweist es, dass der Pufferraum threadsicher ist. OK, es war eine Ausrede, um ein kleines Programm zum Spaß zu schreiben. Eigentlich habe ich es nicht geschrieben. Ich habe online ein Skelett gefunden und modifiziert. Die "FLUSH_BUFFER" -Definition ermöglicht es Ihnen, klarer zu sehen, was passiert. Wenn dieses Makro nicht definiert ist, erhalten Sie einen Sortierpuffer-Test (derselbe Text ohne Zeilenendezeichen). Ich konnte keinen Weg finden, eine sinnvollere Kollision der Fäden zu arrangieren.

Ich nehme an, Sie könnten in mehrere Dateien schreiben. Das Schreiben in eine einzige Datei ist wahrscheinlich ein besserer Test. Das beigefügte Programm ist kein endgültiger Test. Obwohl es erweitert werden könnte, bin ich mir nicht sicher, ob ein Programm wirklich definitiv sein könnte. Fazit: Vielleicht sollten Sie Ihre Anrufe an fprintf() nur MUTEX.

// 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

Die POSIX Threads Spezifikation (AKA Pthreads), das OS X entspricht, erfordert, dass stdio Funktionen Gewinde sicher sind. Es stellt auch die flockfile und funlockfile Funktionen zur Verfügung, um sicherzustellen, dass andere Threads I/O auf einer FILE * nicht verschachteln können, während es gesperrt ist.

Siehe http://pubs.opengroup.org/onlinepubs/007908799/xsh/threads.html, speziell unter dem Abschnitt "Gewindesicherheit".