我在用c编写一个简单的程序,程序有两个线程和两个全局的var,但是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;
}
printf在某种程度上是线程安全的*(参见unlocked_stdio(3)中的讨论......,并考虑flockfile(3))但是stdio是缓冲的,你应该在你的例程中调用fflush(3)。
(printf
可能是线程安全的,因为两个并发的printf
可能不会混合它们的输出,但没有任何关于刷新缓冲区的信息)
所以代码代替
if(i==1000) {
printf("i: %d",i);
fflush(stdout);
}
(然后你会看到一些输出)
顺便说一句,我建议用换行符printf
结束你的大部分\n
格式控制字符串....你还可以通过在你的nanosleep(2)和usleep(3)例程中做一些runi
或runj
来增加一些延迟。
buffering解释说你很失望。由于效率原因,stdout
应该进行缓冲(参见setvbuf(3) ......)。请注意,系统调用(在syscalls(2) for Linux中列出),例如write(2),是非常昂贵的操作。在Linux上使用strace(1)来了解完成了哪些系统调用。
如果你想了解Linux上printf
的实现,请研究你的C标准库的源代码 - 这是free software。它可能是GNU glibc,但可能是像musl-libc等其他东西。
顺便说一句,你的线程永远不会结束(因为runi
和runj
永远不会回来),而你pthread_join
他们。那个电话无限期地阻止着。使用ltrace(1)来观察。
您还可以考虑在第一个sleep(2); fflush(stdout);
之前在main
中添加一些pthread_join
;然后你会观察一些输出。
最后,对于这样的实验,我建议定期打印。用i==1000
替换i%10000 == 0
条件....
你永远不会明确刷新你的stdout
,以便当它的缓冲区(可能是8K字节)已满时,或者在main
结束时(在你的情况下未达到),它会被刷新。 Jonathan Leffler巧妙地评论说你可能需要等一个小时才能完成(缓冲区满状态)。