1. 程式人生 > >c/c++ 基本線程管理 join detach

c/c++ 基本線程管理 join detach

等待 銷毀 主線程 sta 分享圖片 解決 選擇 invalid code

基本線程管理 join detach

join:主線程等待被join線程結束後,主線程才結束。

detach:主線程不等待被detach線程。

問題1:子線程什麽時點開始執行?

std::thread t(fun);執行後,就開始執行了。

問題2:在哪裏調用join或者detach

1,使用detach的話,直接在std::thread t(fun);後面加上t.detach()即可

2,使用join的話,就要自己選擇在代碼的哪個位置調用join。因為在子線程開始之後,但又在join被調用之前發生了異常,所以join的調用就沒有實際發生。

解決方案1:使用try catch

void f(){
  std::thread t(my_func);
  try{
    do_some_work();      
  }
  catch{
    t.join();
    throw;
  }
  t.join();
}

解決方案2:使用一個類包裝thread對象,在這個類的析構函數裏調用join。

#include <iostream>
#include <thread>

using namespace std;

class my_thread{
public:
  explicit my_thread(thread& t_):t(t_){}
  ~my_thread(){
    if(t.joinable()){ //  -------->①
      t.join();//  -------->②
    }
  }
  my_thread(my_thread const&) = delete;//  -------->③
  my_thread& operator=(const my_thread&) = delete;
private:
  thread& t;
};

class func{
public:
  int& data;
  func(int& d):data(d){}
  void operator()(){
    cout << "thread started@@@@@@@@@@@@@@@@@@@@@@@@@@" << endl;
    for(unsigned j = 0; j < 100; ++j){
      cout << j << endl;
    }
  }
};

int main(){
  int state = 0;
  func f(state);
  thread t(f);
  my_thread mt(t);

  //do_something_in_current_thread();
}//  -------->④

github源代碼

知識點1:當程序執行到④處時,局部對象會被銷毀,所以mt的析構函數就會被調用。即使在do_something_in_current_thread();處發生異常了,mt的析構函數也會被調用,所以,join函數不管在什麽情況下都會被調用。

知識點2:在②處調用join前,必須要先判斷是不是joinable①。這很重要,因為只能join一次,多次join就會出下面錯誤。

terminate called after throwing an instance of ‘std::system_error‘
  what():  Invalid argument
Aborted (core dumped)

知識點3:拷貝構造函數和賦值運算符被標記成delete了③,一確保它們不會被編譯器自動提供。復制或賦值一個thread對象是很危險的,因為它可能比它要結合的線程的作用域存在更久。

c/c++ 學習互助QQ群:877684253

技術分享圖片

本人微信:xiaoshitou5854

c/c++ 基本線程管理 join detach