首先看一下join的简单示例:
//joinTest.cc
#include<iostream>
#include<thread>
class Obj
{
public:
Obj() {std::cout << "hello ";}
~Obj() {std::cout << "world\n";}
};
void joinWorker()
{
Obj obj;
std::this_thread::sleep_for(std::chrono::seconds(2));
}
int main()
{
std::thread j(joinWorker);
j.join();
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
运行结果为:
接着把join换成detach试试:
//detachTest.cc
#include<iostream>
#include<thread>
class Obj
{
public:
Obj() {std::cout << "hello ";}
~Obj() {std::cout << "world\n";}
};
void detachWorker()
{
Obj obj;
std::this_thread::sleep_for(std::chrono::seconds(2));
}
int main()
{
std::thread d(detachWorker);
d.detach();
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
输出结果为:
显而易见的是,在执行joinWorker()时,函数内Obj对象的构造和析构函数都被成功调用,但在执行detachWorker()时,Obj对象只调用了构造函数而没有成功调用析构函数。
这是由于,join()是让用户手动管理线程,会阻塞当前线程直到*this所标识的线程结束;detach()不会阻塞当前线程,通过将thread对象分离线程,让线程独立执行,并且当线程运行结束后释放线程的所有资源。
回过头来看例子,由于我们在joinWorker()/detachWorker()中让该线程延迟等待2秒,然后在主线程中只等待1秒,这导致我们的j/d线程的执行时间会大于主线程执行时间。
由于j.join()会阻塞主线程,所以j线程依旧会在主线程结束前结束;但d.detach()并不会阻塞主线程,所有在主线程结束后d线程依然没有结束,所以直到main函数退出,d线程中的Obj对象的析构函数还没有被调用。