thread::join(): 阻塞當前線程,直至 *this 所標識的線程完成其執行。*this 所標識的線程的完成同步於從 join() 的成功返回。html
該方法簡單暴力,主線程等待子進程期間什麼都不能作。thread::join()會清理子線程相關的內存空間,此後thread object將再也不和這個子線程相關了,即thread object再也不joinable了,因此join對於一個子線程來講只能夠被調用一次,爲了實現更精細的線程等待機制,能夠使用條件變量等機制。ios
#include <iostream> #include <thread> #include <chrono> void foo() { std::cout << "foo is started\n"; // 模擬昂貴操做 std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "foo is done\n"; } void bar() { std::cout << "bar is started\n"; // 模擬昂貴操做 std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "bar is done\n"; } int main() { std::cout << "starting first helper...\n"; std::thread helper1(foo); std::cout << "starting second helper...\n"; std::thread helper2(bar); std::cout << "waiting for helpers to finish...\n" << std::endl; helper1.join(); helper2.join(); std::cout << "done!\n"; }
運行結果:c++
starting first helper... starting second helper... foo is started waiting for helpers to finish... bar is started foo is done bar is done done!
異常環境下join,假設主線程在一個函數f()裏面建立thread object,接着f()又調用其它函數g(),那麼確保在g()以任何方式下退出主線程都能join子線程。如:若g()經過異常退出,那麼f()須要捕捉異常後join.編程
#include<iostream> #include<boost/thread.hpp> void do_something(int& i){ i++; } class func{ public: func(int& i):i_(i){} void operator() (){ for(int j=0;j<100;j++) do_something(i_); } public: int& i_; }; void do_something_in_current_thread(){} void f(){ int local=0; func my_func(local); boost::thread t(my_func); try{ do_something_in_current_thread(); } catch(...){ t.join();//確保在異常條件下join子線程 throw; } t.join(); } int main(){ f(); return 0; }
上面的方法看起來笨重,有個解決辦法是採用RAII(資源獲取即初始化),將一個thread object經過棧對象A管理,在棧對象A析構時調用thread::join.按照局部對象析構是構造的逆序,棧對象A析構完成後再析構thread object。以下:併發
#include<iostream> #include<boost/noncopyable.hpp> #include<boost/thread.hpp> using namespace std; class thread_guard:boost::noncopyable{ public: explicit thread_guard(boost::thread& t):t_(t){} ~thread_guard(){ if(t_.joinable()){//檢測是頗有必要的,由於thread::join只能調用一次,要防止其它地方意外join了 t_.join(); } } //thread_guard(const thread_guard&)=delete;//c++11中這樣聲明表示禁用copy constructor須要-std=c++0x支持,這裏採用boost::noncopyable已經禁止了拷貝和複製 //thread_guard& operator=(const thread_guard&)=delete; private: boost::thread& t_; }; void do_something(int& i){ i++; } class func{ public: func(int& i):i_(i){} void operator()(){ for(int j=0;j<100;j++) do_something(i_); } public: int& i_; }; void do_something_in_current_thread(){} void fun(){ int local=0; func my_func(local); boost::thread t(my_func); thread_guard g(t); do_something_in_current_thread(); } int main(){ fun(); return 0; }
thread::detach(): 從 thread 對象分離執行的線程,容許執行獨立地持續。一旦線程退出,則釋放全部分配的資源。調用 detach
後, *this 再也不佔有任何線程。函數
#include <iostream> #include <chrono> #include <thread> void independentThread() { std::cout << "Starting concurrent thread.\n"; std::this_thread::sleep_for(std::chrono::seconds(2)); std::cout << "Exiting concurrent thread.\n"; } void threadCaller() { std::cout << "Starting thread caller.\n"; std::thread t(independentThread); t.detach(); std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Exiting thread caller.\n"; } int main() { threadCaller(); std::this_thread::sleep_for(std::chrono::seconds(5)); std::cout << "back to main.\n"; }
運行結果:this
Starting thread caller. Starting concurrent thread. Exiting thread caller. Exiting concurrent thread. back to main.
若是註釋掉main函數裏的std::this_thread::sleep_for(std::chrono::seconds(5)); 即不等待independentThread 執行完。運行結果以下:spa
Starting thread caller. Starting concurrent thread. Exiting thread caller. back to main.