基本的執行緒管理包括:1、建立執行緒。2、等待它結束或在後台執行。3、向執行緒函式傳遞引數,更改執行緒物件所有權。4、選擇執行緒和使用特定執行緒。
void do_some_work();
std::thread my_thread(do_some_work);
這是最簡單的情況,std::thread還可以使用可呼叫型別(callable type),可以在建立執行緒物件時,在呼叫函式處傳遞乙個物件的例項。
class background_task
};background_task f;
std::thread my_thread(f);
在這種情況下,函式物件在新建立執行緒時
被拷貝到新建執行緒的記憶體中,並在這開始呼叫。必須確保拷貝行為等同於原始物件,否則得不到預期的結果。
在向執行緒建構函式傳遞函式物件時要避免被稱之為」c++最令人煩的語法「。如果你傳遞乙個臨時物件代替命名變數,語法上和乙個函式的宣告一模一樣,這時編譯器會把它當做函式宣告,而不會解釋成物件定義。例如:
std::thread my_thread(background_task());
宣告了乙個函式my_thread,這個函式有乙個引數(指向函式的指標,返回background_task物件),返回乙個std::thread物件,而不是建立新執行緒。這時可以通過3種方法來避免:1像上面那樣命名函式物件。2使用額外的圓括號。3、使用新的標準初始化語法。
第2中方法
std::thread my_thread((background_task()));
加上額外的圓括號後,會阻止編譯器把它解釋成函式的宣告,這樣就能把my_thread解釋成定義std::thread型別物件了。
第3中方法
std::thread my_thread;
使用新的標準初始化語法,用花括號而不是圓括號。
一種型別:可呼叫物件(callable object)可以避免上面的問題是使用拉姆達表示式(lambda expression)。這是c++11的新特性,它允許使用拒不函式,捕捉區域性變數,避免傳入引數。上面例子可以寫成
std::thread my_thread((
do_something();
do_something_else();
});
如果你不等待執行緒結束,那麼要確保執行緒用到的資料一直有效直到執行緒結束。這不是什麼新問題,即使單執行緒的**頁有這樣的問題。(在《linux多執行緒伺服器程式設計》中,有講到過這個問題,使用智慧型指標)。
乙個情形就是函式使用了區域性物件的指標或引用,當函式終止時執行緒並沒有終止。下面看這個例子:
struct func
void operator()() }
};void oops()
在這個例子中,新執行緒在oops函式終止後可能還會執行(分離了新執行緒),如果執行緒還在執行,那麼函式do_something(i)會使用已經銷毀的變數。 執行緒之執行緒的建立
在傳統的unix程序模型中,每個程序只有乙個控制線程。從概念上講,這與基於執行緒的模型中只包含乙個執行緒是相同的。在posix執行緒 pthread 的情況下,程式開始執行時,它也是以單程序中的單個控制線程啟動的,在建立多個控制線程以前,程式的行為與傳統的程序並沒有什麼區別。新增的執行緒可以通過呼叫...
Linux多執行緒之執行緒建立
1.函式 include intpthread create pthread t restrict thread,const pthread attr t restrict attr,void start routine void void restrict arg 引數 thread 為執行緒id...
管理執行緒之執行緒的ID
執行緒的識別符號是執行緒id,執行緒的id型別是std thread id,可以有兩種方式來獲取。第一種,可以通過執行緒關聯的thread object,呼叫object.get id 如果object沒有關聯任何執行緒,那麼get id 返回std thread id預設建構函式,即沒有執行緒。另...