多线程程序上的printf函数

问题描述 投票:-3回答:1

我在用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;
}
c multithreading
1个回答
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)usleep(3)例程中做一些runirunj来增加一些延迟。

buffering解释说你很失望。由于效率原因,stdout应该进行缓冲(参见setvbuf(3) ......)。请注意,系统调用(在syscalls(2) for Linux中列出),例如write(2),是非常昂贵的操作。在Linux上使用strace(1)来了解完成了哪些系统调用。

如果你想了解Linux上printf的实现,请研究你的C标准库的源代码 - 这是free software。它可能是GNU glibc,但可能是像musl-libc等其他东西。

顺便说一句,你的线程永远不会结束(因为runirunj永远不会回来),而你pthread_join他们。那个电话无限期地阻止着。使用ltrace(1)来观察。

您还可以考虑在第一个sleep(2); fflush(stdout);之前在main中添加一些pthread_join;然后你会观察一些输出。

最后,对于这样的实验,我建议定期打印。用i==1000替换i%10000 == 0条件....

你永远不会明确刷新你的stdout,以便当它的缓冲区(可能是8K字节)已满时,或者在main结束时(在你的情况下未达到),它会被刷新。 Jonathan Leffler巧妙地评论说你可能需要等一个小时才能完成(缓冲区满状态)。

当心race conditionsundefined behavior

© www.soinside.com 2019 - 2024. All rights reserved.