以下是使用pthreads的程序。
#include <pthread.h> // posix threads
#include <stdio.h>
#include <stdlib.h>
/* to compile use -lpthread */
void * sample_thread(void *);
#define MAX 10
int main()
{
pthread_t tid;
pthread_attr_t attr;
int k;
pthread_attr_init(&attr); // set default attributes
pthread_create(&tid, &attr, sample_thread, NULL); // create new thread
// sample_thread will run as the new thread
for(k=0; k<MAX; k++) {
printf("Hi I'am %s %d \n",__func__,k);
}
//this would kill all the threads,
}
void * sample_thread(void * p)
{
int k;
for(k=0; k<MAX; k++) {
printf("Hi I'am %s %d \n",__func__,k);
}
}
每次运行程序时,我都希望从主线程和子线程获得不同数量的执行数(因为主线程可能会在子进程之前退出)。我有时会得到这个预期的输出。但我得到如下输出,我无法理解为什么。
Hi I'am main 0
Hi I'am main 1
Hi I'am main 2
Hi I'am main 3
Hi I'am main 4
Hi I'am main 5
Hi I'am main 6
Hi I'am main 7
Hi I'am main 8
Hi I'am main 9
Hi I'am sample_thread 0
Hi I'am sample_thread 0
Hi I'am sample_thread 1
Hi I'am sample_thread 2
Hi I'am sample_thread 3
Hi I'am sample_thread 4
Hi I'am sample_thread 4
Hi I'am sample_thread 5
为什么样本线程0和4打印两次?
答案 0 :(得分:10)
正如@R ..在评论中强调的那样,在glibc的实现中似乎是a bug(假设您使用的是Linux - 我可以在使用GCC 4.9.1编译的Linux 2.17上重现这一点) ,exit()
无法确保,当刷新和关闭流时,当多个线程使用stdout时,一个线程调用它时没有竞争。
flockfile
手册中的以下内容清楚地表明观察到的行为不正确:
stdio函数是线程安全的。这是通过 为每个FILE对象分配一个lockcount和(如果lockcount为 非零)一个拥有的线程。对于每个库调用,这些函数 等到FILE对象不再被其他对象锁定 线程,然后锁定它,执行请求的I / O,并解锁对象 试。
鉴于此,我们在此处观察到的特定情况下,可以将以下选项视为一种解决方法(因为对错误报告没有响应)。
两个线程“共享”stdout
流,我认为,由于主线程过早退出,会打印“额外”输出。
printf
缓冲区(在sample_thread()
中)输出,在它清除缓冲区之前(由于printfs中的\n
),主线程退出。因此,当进程退出时强制刷新stdout
缓冲区。
要修复,
1)在创建主题之前,您可以在setbuf()
中调用main()
:
setbuf(stdout, NULL);
到而不是缓冲区stdout
。
或者
2)在两个线程中调用pthread_exit()
,以便在任一线程死亡时继续进行。
或者
3)在主线程中调用pthread_join()
,以便主线程等待sample_thread
线程的完成。
其中任何一个都可以避免这个问题。