multithreading程序中的意外输出

以下是使用pthreads的程序。

#include  // posix threads #include  #include  /* 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打印两次?

正如@R ..在评论中强调的那样,这似乎是glibc实现中的一个错误 (假设您使用的是Linux – 我可以在使用GCC 4.9.1编译的Linux 2.17上重现这一点),在那个exit()不确定,当刷新和关闭流时,当多个线程使用stdout时,一个线程调用它时没有竞争。

flockfile手册中的以下内容清楚地表明观察到的行为不正确:

stdio函数是线程安全的。 这是通过为每个FILE对象分配一个lockcount和(如果lockcount非零)一个拥有线程来实现的。 对于每个库调用,这些函数等待,直到FILE对象不再被另一个线程锁定,然后锁定它,执行请求的I / O,并再次解锁对象。

鉴于此,我们在此处观察到的这种特殊情况可以考虑以下选项作为解决方法(因为对错误报告没有响应)。


两个线程“共享” stdout流,我认为,由于主线程的过早退出,打印了“额外”输出。

printf buffer(在sample_thread() )输出,在它清除缓冲区之前(由于printfs中的\n ),主线程退出。 因此在进程退出时强制刷新stdout缓冲区。

修理,

1)你可以在创建线程之前在main()调用setbuf()

 setbuf(stdout, NULL); 

根本不缓冲stdout

要么
2)在两个线程中调用pthread_exit() ,以便在任一线程死亡时进程继续。

要么
3)在主线程中调用pthread_join() ,以便主线程等待sample_thread线程的完成。

其中任何一个都可以避免这个问题。