#include < iostream >
#include < pthread.h >
using namespace std;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* Func(void *)
{
pthread_mutex_lock(&mutex);
cout << "First thread execution" << endl;
pthread_mutex_unlock(&mutex);
}
int main()
{
pthread_t th1;
pthread_create(&th1, NULL, Func, NULL);
pthread_mutex_lock(&mutex);
cout << "In main thread" << endl;
pthread_mutex_lock(&mutex);
// pthread_join(th1, NULL); // Note this code is commented
return 0;
}
我已经在linux fedora 22(也在http://www.cpp.sh/)上执行了以下程序大约20次,并且在20次执行中,我发现了以下输出:-
Output1:
In main thread
First thread execution
Output2:
First thread execution
In main thread
Output3:
In main thread
Output4:
In main thread
First thread execution
First thread execution
输出1到3是预期的,因为主线程没有等待子线程退出。两个线程(主线程和子线程)的执行顺序完全依赖于内核线程调度。
但是输出4很奇怪!!First thread execution
被打印两次!!
现在,如果我在取消注释代码'pthread_join(th1, NULL)'或添加'pthread_exit(NULL)'后运行程序,我不会得到奇怪的输出(即First thread execution
从未打印两次),即使我运行代码10000次。
我对专家的问题是:
- 没有pthread_join/pthread_exit在后台发生了什么,所以
First thread execution
已经打印了2次?
pthread_join的职责是获取特定线程的退出代码,在成功调用pthread_join后,内核将释放该特定线程的资源。如果我不在一个可接合的线程上调用pthread_join,那么它将导致资源泄漏,但是为什么上面提到奇怪的行为??
我们可能会说,这是未定义的行为,但如果有专家对此提供技术解释就太好了。
- 如何pthread_join/pthread_exit可以防止上述奇怪的行为?由于奇怪的行为没有出现,它在这里隐藏着什么?
提前感谢专家…
我曾在类似的情况下观察到这种双打印。当您的线程在write
系统调用中等待执行其正常输出时,特别是在此堆栈中:
#0 0x00007ffff78f4640 in write () from /lib64/libc.so.6
#1 0x00007ffff788fb93 in _IO_file_write () from /lib64/libc.so.6
#2 0x00007ffff788fa72 in new_do_write () from /lib64/libc.so.6
#3 0x00007ffff7890e05 in _IO_do_write () from /lib64/libc.so.6
#4 0x00007ffff789114f in _IO_file_overflow () from /lib64/libc.so.6
程序被正常终止,正常终止导致输出子系统刷新所有缓冲区。stdin上的输出缓冲区还没有被标记为空闲(write系统调用还没有返回),所以它被再次写出来:
#0 0x00007ffff78f4640 in write () from /lib64/libc.so.6
#1 0x00007ffff788fb93 in _IO_file_write () from /lib64/libc.so.6
#2 0x00007ffff788fa72 in new_do_write () from /lib64/libc.so.6
#3 0x00007ffff7890e05 in _IO_do_write () from /lib64/libc.so.6
#4 0x00007ffff7890140 in _IO_file_sync () from /lib64/libc.so.6
#5 0x00007ffff7891f56 in _IO_default_setbuf () from /lib64/libc.so.6
#6 0x00007ffff7890179 in _IO_file_setbuf () from /lib64/libc.so.6
#7 0x00007ffff7892703 in _IO_cleanup () from /lib64/libc.so.6
#8 0x00007ffff78512f8 in __run_exit_handlers () from /lib64/libc.so.
在任何情况下,连接你的线程(如果你使用c++线程,它会提醒你这样做)或同步访问输出流
主线程可能比派生线程更早结束。
主线程的结束意味着整个进程的结束,同时所有线程也会突然关闭。这可能会调用未定义的行为,因此任何事情都可能发生。
绕过这个
- 从
main()
使用pthread_join()
加入生成的线程, - 或者使用
pthread_exit()
结束主线程,它只结束主线程,不结束进程。