pthreads编程疑问:thread2的printf输出为何会重复?
为什么你的pthreads代码会出现thread2输出重复的情况?
这问题挺典型的,我来帮你一步步拆解原因:
核心根源:未初始化的pthread_t变量被误用
你的全局变量thread2在主线程创建它之前,默认初始化为0。当thread1被先创建并调度执行时,它会立刻调用pthread_join(thread2, NULL)——这时候传入的是一个无效的线程ID。
在你使用的Ubuntu 16.04的NPTL线程库(搭配GCC 5.4)中,pthread_join(0, NULL)有一个不符合POSIX规范的特殊行为:它不会返回错误,反而会错误地返回成功(ret=0)。这就导致thread1误以为已经join到了thread2,直接退出。
进程退出引发的输出混乱
当thread1退出后,主线程的pthread_join(thread1, NULL)完成,随即触发进程退出流程:
- 进程会调用
exit(),该函数会强制刷新所有stdio流的缓冲区。 - 同时,进程会向所有仍在运行的线程(此时就是thread2)发送终止信号,强制它们停止。
但此时thread2可能还在执行中:
- 它可能刚执行完第一个
printf,第二个printf的内容还在用户态缓冲区里; - 或者它正处于printf的执行过程中,进程退出的缓冲区刷新操作和thread2自身的printf操作发生了冲突;
- 更严重的情况是,进程退出时会回收线程的栈资源,thread2的栈被破坏后,printf的字符串指针指向的内存被重复读取或写入,导致输出重复。
这就是你看到exit from 2.....重复输出的原因。
验证逻辑的修复小实验
你可以修改代码,先创建thread2再创建thread1:
// 交换创建顺序 ret2 = pthread_create(&thread2, NULL, thread2_entry, NULL); ret1 = pthread_create(&thread1, NULL, thread1_entry, NULL);
这样thread1执行pthread_join(thread2, NULL)时,thread2已经存在,不会再出现无效join的情况,输出也会变得稳定,不会有重复内容。
额外的实践建议
- 永远不要使用未初始化的
pthread_t变量调用pthread_join,这属于未定义行为,不同系统/库版本的表现可能差异很大。 - 如果需要线程间的同步,优先使用条件变量、互斥锁等同步原语,而不是依赖线程创建的顺序(线程调度是完全不可预测的)。
内容的提问来源于stack exchange,提问作者AsaMyth
相关产品推荐
相关产品推荐

