Joining and Detaching Threads

C++11 Multithreading – Part 2: Joining and Detaching Threads

Joining Threads with std::thread::join()

一个线程启动后,另一个线程可以等待该线程完成。这个特别的需求可以用join来实现:

1
2
std::thread th(funcPtr);
th.join();

Detaching Threads using std::thread::detach()

被分离的线程也叫守护(daemon)/后台(background)线程,这个需求可以调用std::function来完成:

1
2
std::thread th(funcPtr);
th.detach();

Be careful with calling detach() and join() on Thread Handles

Case 1: Never call join() or detach() on std::thread object with no associated executing thread std::thread threadObj( (WorkerThread()) ); threadObj.join(); threadObj.join(); // It will cause Program to Terminate

比如在一个没有相关线程的线程上执行join或者detach都会导致程序终止:

1
2
3
4
5
6
7
8
std::thread threadObj( (WorkerThread()) );
threadObj.join();
threadObj.join(); // It will cause Program to Terminate


std::thread threadObj( (WorkerThread()) );
threadObj.detach();
threadObj.detach(); // It will cause Program to Terminate

为了避免这个问题,每次调用join()或者detach()之前都应该检查线程状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
std::thread threadObj( (WorkerThread()) );
if(threadObj.joinable())
{
std::cout<<"Detaching Thread "<<std::endl;
threadObj.detach();
}
if(threadObj.joinable())
{
std::cout<<"Detaching Thread "<<std::endl;
threadObj.detach();
}

std::thread threadObj2( (WorkerThread()) );
if(threadObj2.joinable())
{
std::cout<<"Joining Thread "<<std::endl;
threadObj2.join();
}
if(threadObj2.joinable())
{
std::cout<<"Joining Thread "<<std::endl;
threadObj2.join();
}

Case 2 : Never forget to call either join or detach on a std::thread object with associated executing thread

如果一个线程还有相关联的在执行的线程,但却没有对此执行join()或者detach(),那么在destructor中会终止该程序。因为destructor会检查线程是否joinable。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <thread>
#include <algorithm>
class WorkerThread
{
public:
void operator()()
{
std::cout<<"Worker Thread "<<std::endl;
}
};
int main()
{
std::thread threadObj( (WorkerThread()) );
// Program will terminate as we have't called either join or detach with the std::thread object.
// Hence std::thread's object destructor will terminate the program
return 0;
}