Des*_*PRG 9 c multithreading pthreads
以下是使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
每次运行程序时,我都期望从主线程和子线程获得不同数量的执行数(因为主线程可能在子进程之前退出).我有时会得到这个预期的输出.但是我得到了如下输出,我无法理解为什么.
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
Run Code Online (Sandbox Code Playgroud)
为什么示例线程0和4打印两次?
P.P*_*.P. 10
由于强调了@R ..在评论,这似乎是一个bug中的glibc的实现(假设你使用的是Linux -我可以重现这个在Linux上使用2.17 4.9.1 GCC编译),在exit()不确保在刷新和关闭流时,当多个线程使用stdout时,一个线程调用它时没有竞争.
flockfile手册中的以下内容清楚地表明观察到的行为不正确:
stdio函数是线程安全的.这是通过为每个FILE对象分配一个lockcount和(如果lockcount非零)一个拥有线程来实现的.对于每个库调用,这些函数一直等到FILE对象不再被另一个线程锁定,然后将其锁定,执行请求的I/O并再次解锁对象.
鉴于此,我们在此处观察到的这种特殊情况可以考虑以下选项作为解决方法(因为对错误报告没有响应).
两个线程"共享" stdout流,我认为,由于主线程的过早退出,打印出"额外"输出.
printf缓冲(in sample_thread())输出,在它清除缓冲区之前(由于\n在printfs中),主线程退出.因此,stdout当进程退出时强制刷新缓冲区.
修理,
1)你可以setbuf()在main()创建线程之前调用 :
setbuf(stdout, NULL);
Run Code Online (Sandbox Code Playgroud)
以不缓冲stdout可言.
或者
2)调用pthread_exit()两个线程,以便在任一线程死亡时继续进程.
或者
3)pthread_join()在主线程中调用,以便主线程等待线程的完成sample_thread.
其中任何一个都可以避免这个问题.