我在c中编写一个简单的程序,该程序有两个线程和两个全局变量,但printf函数不起作用,我知道printf不是线程安全的,如果我很好的话在打印中添加\ n它会起作用,但是我不明白为什么没有它就无法工作? 我正在添加代码,
#include <pthread.h>
#include <stdio.h>
int i;
int j;
void* runi(void* _temp)
{
while(1)
{
i++;
if(i==1000)
{
printf("i: %d",i);
}
}
return NULL;
}
void* runj(void* _temp)
{
while(1)
{
j++;
if(j==1000)
{
printf("j: %d",j);
}
}
return NULL;
}
main ()
{
pthread_t threadI,threadJ;
pthread_create(&threadI,NULL,runi,NULL);
pthread_create(&threadJ,NULL,runj,NULL);
pthread_join(threadI,NULL);
pthread_join(threadJ,NULL);
return 0;
}
答案 0 :(得分:3)
printf在某种程度上是线程安全的 * (参见unlocked_stdio(3)中的讨论......,并考虑flockfile(3))但是stdio是缓冲的,你应该调用fflush(3)在你的日常生活中。
(printf
可能是线程安全的,因为两个并发的printf
可能不会混合它们的输出,但没有任何关于刷新缓冲区的信息)
所以代码
if(i==1000) {
printf("i: %d",i);
fflush(stdout);
}
(然后你会看到一些输出)
顺便说一句,我建议您使用换行符printf
结束大多数\n
格式控制字符串....您还可以通过执行nanosleep(2)或{{3}来添加一些延迟在你的runi
&amp; runj
例程。
usleep(3)解释说你很失望。出于效率原因,应缓存stdout
(请参阅buffering ...)。请注意,系统调用(在setvbuf(3)中列出的Linux)(例如syscalls(2))是非常昂贵的操作。在Linux上使用write(2)来了解已完成的系统调用。
如果您想了解Linux上printf
的实现,请研究C标准库的源代码 - strace(1)。它可能是GNU free software,但可能是glibc等其他东西。
runi
和runj
永远不会返回),你pthread_join
就是这样。那个电话无限期地阻止着。使用musl-libc来观察。
您还可以考虑在第一个sleep(2); fflush(stdout);
之前的main
中添加一些pthread_join
;然后你会观察一些输出。
最后,对于这样的实验,我建议定期打印。将i==1000
条件替换为i%10000 == 0
....
你永远不会明确刷新你的stdout
,以便当它的缓冲区(可能是8K字节)已满时,或者在main
(未)到达时,它会被刷新你的情况)。 ltrace(1)巧妙地评论说你可能需要等待一个小时才能完成(缓冲区满状态)。