我最近根据POSIX 1003.1c开始学习pthreads的奇迹.
PThreads可能看起来很复杂,但它们基本上是我们在类中用来创建并行行为的简单线程:https://computing.llnl.gov/tutorials/pthreads/
在我还在学习的时候,我的老师给了我们一个C代码来玩具:
/* Creates two threads, one printing 10000 "a"s, the other printing
10000 "b"s.
Illustrates: thread creation, thread joining. */
#include <stddef.h>
#include <stdio.h>
#include <unistd.h>
#include "pthread.h"
void * process(void * arg)
{
int i;
fprintf(stderr, "Starting process %s\n", (char *) arg);
for (i = 0; i < 100; i++) {
write(1, (char *) arg, 1);
// fprintf(stdout, (char *) arg, 1);
}
return NULL;
}
int main()
{
int retcode;
pthread_t th_a, th_b;
void * retval;
retcode = pthread_create(&th_a, NULL, process, "a");
if (retcode != 0) fprintf(stderr, "create a failed %d\n", retcode);
retcode = pthread_create(&th_b, NULL, process, "b");
if (retcode != 0) fprintf(stderr, "create b failed %d\n", retcode);
retcode = pthread_join(th_a, &retval);
if (retcode != 0) fprintf(stderr, "join a failed %d\n", retcode);
retcode = pthread_join(th_b, &retval);
if (retcode != 0) fprintf(stderr, "join b failed %d\n", retcode);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
一切正常但我不明白为什么我的输出顺序因使用write或而有所不同fprintf.
当我使用时,write我得到一个随机输出的字母,如下所示:
Starting process a
aaaaaaaaaaaaaaaaaaaaaaaaaaaaStarting process b
aaababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
Run Code Online (Sandbox Code Playgroud)
但是当我使用时,fprintf我总是得到类似于的输出:
Starting process a
Starting process b
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaababbabaabaabaababbabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
Run Code Online (Sandbox Code Playgroud)
在这种情况下,文本"Starting process"始终首先出现,并且不与输出的其余部分混合.为什么会这样?是因为write速度快而且fprintf速度慢吗?
作为C程序员,我应该使用哪一个?为什么?
Pot*_*ter 12
write 是系统调用:它将给定的字符直接发送到操作系统,操作系统(理论上,通常在实践中)将它们立即发送到输出设备,如屏幕或磁盘.
fprintf(以及fwrite任何带FILE *参数的东西)是一个库调用,它在发送之前缓冲或收集程序中的数据.这允许它发送更大,更均匀的数据块,从而提高效率.
你看到的write是每个调用导致一个线程切换,因为程序等待操作系统确认写入是否成功.当一个线程在等待时,另一个线程会有时间.
有fprintf,它从来没有做过这么特别的事情.它实际上只是一个用as 填充数组的线程,直到它完成.在收到填充缓冲区(via write)之前,操作系统不是更明智的.然后,因为第一个线程没有更多的工作,它运行第二个.如果你打印了更多的字符,你会看到fprintf交错a的和b,因为块被发送到操作系统.
至于"快"和"慢",write在发送其输出时更直接,但fprintf在几乎所有其他方式都更快,并且是一般正确选择(或fwrite更相似write).