C++多线程中的join, detach, joinable
回收子线程的资源有两种方法——join和detach:
- join的意思是父线程等待子线程结束,在子线程结束时,负责回收子线程的资源。
- detach的含义是父线程和子线程相互分离,即使父线程结束了,只要主线程没有结束,子线程就会继续正常运行。在子线程结束时,负责回收子线程的资源。
- joinable()函数是一个布尔类型的函数,他会返回一个布尔值来表示当前的线程是否是可执行线程(能被join或者detach),因为相同的线程不能join两次,也不能join完再detach,同理也不能detach完再join,所以joinable函数就是用来判断当前这个线程是否可以joinable的。通常不能被joinable有以下几种情况:
1)thread t;
:t由缺省构造函数构建,此时线程未传入具体的线程函数。此时t.joinable()
返回0,表示不可被join或者detach
2)该thread被move过(包括move构造和move赋值)。【move指的是:线程的所有权将发生转移,原有线程对象的相关标识被清空,失去线程的控制权。其原有线程类对象ID变为0,joinable变为为false。(参考自:C++11中线程所有权转移分析)】
3)该线程已经被join或者detach过。
参考:C++多线程中的join, detach, joinable
没有join和detach时
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;
void func2(){
cout<<"22222"<<endl;
}
void func(){
cout<<"11111111"<<endl;
thread t(func2);
cout<<"33333333"<<endl;
}
int main(){
func();
cout<<"main"<<endl;
sleep(10);
return 0;
}
结果:
g++ -Wall -g -std=c++11 -pthread test2.cpp -o test2
./test2
11111111
33333333
terminate called without an active exception
Aborted (core dumped)
在函数func中,启动线程t,但是线程t没有执行join或detach,那么在函数func执行完毕的时候就会发生错误,从而中断整个程序。
detach
detach的含义是父线程和子线程相互分离,即使父线程结束了,只要主线程没有结束,子线程就会继续正常运行。
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;
void func(){
sleep(1);
cout<<"22222"<<endl;
}
void func2(){
cout<<"11111111"<<endl;
thread t(func);
t.detach();
cout<<"33333333"<<endl;
}
void func3(){
sleep(10);
}
int main(){
thread t2(func2);
thread t3(func3);
t3.join();
cout<<"main"<<endl;
return 0;
}
父线程t2创建子线程t,并使用detach分离父子线程。当t2结束时,因为此时主线程因为等待t3而未结束,所以t并不会结束。
虽说detach将父线程和子线程分离了,但是如果父线程时主线程的话,主线程结束子线程也会结束,此时子线程可能还有任务没有完成,比如:使用detach时,如果子线程还没清理垃圾,主线程就结束了,那么就会导致内存溢出