執行緒是在作業系統層面支援的,所以多執行緒的學習建議還是先找一本linux系統程式設計類的書,了解linux提供執行緒的api,了解使用執行緒設計程式的基本操縱。完全使用系統呼叫編寫多執行緒程式是痛苦,現在有很多封裝好的多執行緒庫,幫助簡單快速的使用執行緒程式設計,了解作業系統提供的api對理解多執行緒程式和使用封裝好的多執行緒庫是非常有幫助的。簡單來說,linux作業系統提供了四類系統用於多程式程式,分別執行緒的建立、銷毀、執行緒同步的互斥量(mutex)、條件量(cond),訊號量(sem)。
參考:linux 執行緒同步的三種方法
c++11從語言層面支援多執行緒操作,本質上是對系統呼叫的封裝,極大的方便了開發人員。
1、
執行緒類thread,提供raii式執行緒的建立和銷毀。建立執行緒時傳入執行緒要執行的**段(函式、lamda表示式)和引數,thread析構函式會自動銷毀執行緒。
2、
a.作業系統提供mutex可以設定屬性,c++11根據mutext的屬性提供四種的互斥量,分別是
b. mutex成員函式加鎖解鎖
c. mutex raii式的加鎖解鎖
3、
條件變數的使用要結合條件、互斥量、條件變數三者一起使用。執行緒在檢測條件之前使用mutex加鎖,滿足某種條件時執行緒使用條件變數的wait操作進入阻塞狀態。當其它的執行緒修改條件,啟用該條件變數阻塞的執行緒,阻塞的執行緒的重新加鎖檢測條件。條件變數提供wait和notify兩種操作。
// condition_variable example
#include // std::cout
#include // std::thread
#include // std::mutex, std::unique_lock
#include // std::condition_variable
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id (int id)
void go()
int main ()
4、訊號量(csemaphore)c++11多執行緒庫沒有提供訊號量的類,但是很容易通過條件變數、互斥量自己實現。
//訊號量類
class csemaphore
void wait()
value--;
}bool try_wait()
void post()
cv.notify_one();
}};
5、原子操作針對多執行緒的共享資料的儲存讀寫,多執行緒指令交叉可能造成未知的錯誤(undefine行為),需要限制併發程式以某種特定的順序執行,除了前面介紹的互斥量加鎖的操縱,還可以使用c++11中提供的原則操作(atomic)。原子操作使得某個執行緒對共享資料的操作要不一步完成,要不不做。
a、std::atomic_flag是乙個bool原子型別有兩個狀態:set(flag=true) 和 clear(flag=false),必須被atomic_flag_init初始化此時flag為clear狀態,相當於靜態初始化。一旦atomic_flag初始化後只有三個操作:test_and_set,clear,析構,均是原子化操作。atomic_flag::test_and_set檢查flag是否被設定,若被設定直接返回true,若沒有設定則設定flag為true後再返回false。atomic_clear()清楚flag標誌即flag=false。不支援拷貝、賦值等操作,這和所有atomic型別一樣,因為兩個原子型別之間操作不能保證原子化。atomic_flag的可操作性不強導致其應用侷限性,還不如atomic。
b、atomic模板類。t必須滿足trivially copy type。定義了拷貝/移動/賦值函式;沒有虛成員;基類或其它任何非static成員都是trivally copyable。典型的內建型別bool、int等屬於trivally copyable type。注意某些原子操作可能會失敗,比如atomic、atomic,,沒有原子算術操作針對浮點數。
atomic特別針對整數和指標做了特化。整數包括har, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, char16_t, char32_t, wchar_t。由於在實際中,用得比較多的原子型別是整數,下面以整數原子型別介紹原子型別的操作函式
針對整型特化,增加的一些操作函式:
6、future
參考:c++併發實戰13:std::future、std::async、std::promise、std::packaged_task
多執行緒程式設計時,一方面要注意多執行緒共享變數的訪問的安全性,另一方面有些非同步任務之間會有結果的傳遞。c++11標準提供了幾種非同步任務處理機制。通常thread不能直接返回執行的結構(可以通過傳遞應用,指標),而在非同步處理當中很多時候乙個執行緒(privider)建立某個執行緒(executor)處理某個任務,provider在某個時候獲取executor執行結果,如果executor沒有完成任務,provider執行緒就會阻塞等待,直到executor執行緒完成任務,返回結果。
std::future可用於非同步任務中獲取任務結果,但是它只是獲取結果而已,真正的非同步呼叫需要配合std::async,std::packaged_task,std::promise。async是個模板函式,packaged_task和promise是模板類,通常模板例項化引數是任務函式。
a、aysnc函式+future 模式
std::futurefut = std::async (is_prime,313222313);
這裡裡async自動建立乙個後台執行緒,執行任務is_prime函式,並將計算結果儲存在myfuture中,這裡future的模板引數要和任務task返回型別一致為bool.
b、packaged_task+future
std::packaged_task內部包含了兩個最基本的元素。一、被包裝的任務,任務是乙個可呼叫的物件,函式物件、函式指標。二、共享狀態(shared state),用於儲存任務的返回值,使用std::future物件非同步訪問共享狀態。
std::packaged_task 的共享狀態的生命週期一直持續到最後乙個與之相關聯的物件被釋放或者銷毀為止。
具體例項參考:
c、promise + future
aync和packaged_task,是provider執行緒獲取executor執行緒的結果。promise是provider執行緒通過future物件項executor執行緒傳遞引數。
promise 物件可以儲存某一型別 t 的值,該值可被 future 物件讀取(可能在另外乙個執行緒中)。在 promise 物件構造時可以和乙個共享狀態(通常是std::future)相關聯,並可以在相關聯的共享狀態(std::future)上儲存乙個型別為 t 的值。
可以通過 get_future 來獲取與該 promise 物件相關聯的 future 物件,呼叫該函式之後,兩個物件共享相同的共享狀態(shared state)
#include // std::cout
#include // std::ref
#include // std::thread
#include // std::promise, std::future
void print_int(std::future& fut)
int main ()
●編號469,輸入編號直達本文
●輸入m獲取文章目錄
c語言與c++程式設計
分享c/c++技術文章
c 11 多線執行緒 future
std promise 類介紹 promise 物件可以儲存某一型別 t 的值,該值可被 future 物件讀取 可能在另外乙個執行緒中 因此 promise 也提供了一種執行緒同步的手段。在 promise 物件構造時可以和乙個共享狀態 通常是std future 相關聯,並可以在相關聯的共享狀態...
C 11中多執行緒
std lock guard是raii模板類的簡單實現,功能簡單。std lock guard 在建構函式中進行加鎖,析構函式中進行解鎖。鎖在多執行緒程式設計中,使用較多,因此c 11提供了lock guard模板類 在實際程式設計中,我們也可以根據自己的場景編寫resource guardraii...
C 11 多執行緒
新特性之描述 雖然 c 11 會在語言的定義上提供乙個記憶體模型以支援執行緒,但執行緒的使用主要將以 c 11 標準庫的方式呈現。c 11 標準庫會提供型別 thread std thread 若要執行乙個執行緒,可以建立乙個型別 thread 的實體,其初始引數為乙個函式物件,以及該函式物件所需要...