OS X符合的POSIX线程规范(AKA Pthreads)要求stdio函数是线程安全的.它还提供了flockfile
和funlockfile
功能,以确保其他线程不能在文件上交错I/O*,而被锁定.
请参阅http://pubs.opengroup.org/onlinepubs/007908799/xsh/threads.html,特别是标题为" 线程安全 "的部分.
这是一个很好的问题,尽管类似的问题已经在这里被问过很多次了。我对 OSX 方面很感兴趣,因为我试图自己加快了解该系统的速度。(也许你应该添加 OSX 标签)
我认为fprintf() 在 OSX 上是线程安全的。我这样做的第一个原因是达尔文人正在朝这个方向发展,他们选择放弃老式的全局“errno”而转而使用函数 errno() 就证明了这一点。有关文档,只需遵循“/usr/include/errno.h”即可。没有它,libc 的东西都不是线程安全的。然而,使用 errno() 函数并不能证明有关 fprintf() 的任何信息。这只是一个开始。我相信每个人都知道至少有一种情况是苹果没有实现一个好主意。
我相信 fprintf() 的“线程安全”的另一个原因是源代码,它应该是“真实的东西”,至少直到 10.6 Apple 关闭(部分/全部)OSX 为止。扫描“MT-Safe”代码,您将看到一条声明,声明非语言环境版本的“vfprintf()”是线程安全的。再说一遍,这并不能证明什么。然而,它是您想要的一种文档形式。
我相信 fprintf() 是线程安全的最后一个原因是一个测试用例。这也不能证明什么。也许这证明了缓冲区空间是线程安全的。好吧,这是为了好玩而编写一个小程序的借口。其实不是我写的。我在网上找到了一个骨架,并对其进行了修改。“FLUSH_BUFFER”定义可以让您更清楚地看到发生了什么。如果未定义该宏,您将获得“某种”缓冲区测试(相同的文本,但没有一些行终止符)。我无法找到一种方法来安排更有意义的线程冲突。
我猜你可能正在写入多个文件。写入单个文件可能是更好的测试。随附的程序不是最终的测试。虽然它可以延长,但我不确定任何计划是否真的是确定的。底线:也许您应该对 fprintf() 的调用进行 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);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
967 次 |
最近记录: |