当使用 std::thread 对象执行线程时,必须要调用 join() (或者 detach(),由于 detach() 可以立即调用,所以这里只考虑 join())
1 #include <iostream> 2 #include <thread> 3 #include <chrono> 4 5 using namespace std; 6 7 void threadInvoker() 8 { 9 cout << "thread begin\n"; 10 this_thread::sleep_for(chrono::milliseconds(2000)); 11 cout << "thread end\n"; 12 } 13 14 void doSomething() 15 { 16 cout << "doSomething begin\n"; 17 this_thread::sleep_for(chrono::milliseconds(4000)); 18 cout << "doSomething end\n"; 19 } 20 21 void doOther() 22 { 23 } 24 25 void f() 26 { 27 thread t(threadInvoker); 28 29 doSomething(); 30 31 doOther(); 32 t.join(); 33 } 34 35 int main() 36 { 37 f(); 38 }
编译:g++ -std=c++11 -pthread test.cpp
如果 doSomething() 会产生异常,则尝试捕获
1 #include <iostream> 2 #include <thread> 3 #include <chrono> 4 5 using namespace std; 6 7 void threadInvoker() 8 { 9 cout << "thread begin\n"; 10 this_thread::sleep_for(chrono::milliseconds(2000)); 11 cout << "thread end\n"; 12 } 13 14 void doSomething() 15 { 16 cout << "doSomething begin\n"; 17 this_thread::sleep_for(chrono::milliseconds(4000)); 18 throw 0; 19 cout << "doSomething end\n"; 20 } 21 22 void doOther() 23 { 24 } 25 26 void f() 27 { 28 thread t(threadInvoker); 29 30 try { 31 doSomething(); 32 } 33 catch (...) { 34 cout << "catch exception\n"; 35 t.join(); 36 return; 37 } 38 39 doOther(); 40 t.join(); 41 } 42 43 int main() 44 { 45 f(); 46 }
但是必须在 catch 块里调用 t.join(),否则会 crash。如果条件一多,很可能会在某个分支下遗忘 t.join()。
因此可以使用 RAII 来避免,在析构函数中进行 join()
1 #include <iostream> 2 #include <thread> 3 #include <chrono> 4 5 using namespace std; 6 7 class ThreadGuard 8 { 9 public: 10 explicit ThreadGuard(thread& t):mT(t) {} 11 ~ThreadGuard() 12 { 13 if (mT.joinable()) { 14 cout << "join\n"; 15 mT.join(); 16 } 17 } 18 ThreadGuard(ThreadGuard const&) = delete; 19 ThreadGuard& operator=(ThreadGuard const&) = delete; 20 private: 21 thread& mT; 22 }; 23 24 void threadInvoker() 25 { 26 cout << "thread begin\n"; 27 this_thread::sleep_for(chrono::milliseconds(2000)); 28 cout << "thread end\n"; 29 } 30 31 void doSomething() 32 { 33 cout << "doSomething begin\n"; 34 this_thread::sleep_for(chrono::milliseconds(4000)); 35 throw 0; 36 cout << "doSomething end\n"; 37 } 38 39 void doOther() 40 { 41 } 42 43 void f() 44 { 45 thread t(threadInvoker); 46 ThreadGuard tg(t); 47 48 try { 49 doSomething(); 50 } 51 catch (...) { 52 cout << "catch exception\n"; 53 return; 54 } 55 56 doOther(); 57 } 58 59 int main() 60 { 61 f(); 62 }
利用局部对象的析构保证 join() 的调用