在多執行緒程式中,往往會遇到執行緒中資源同步問題,同步問題可以劃分為兩類,一類為共享一個資源,一類為給每個執行緒分配一個資源
一:給每個執行緒分配一個資源
1:定義執行緒變數,在變數名前面加上_thread,該變數就會申明為執行緒變數
但是同時C++中對__thread變數的使用有額外的限制:
1。 在C++中,如果要在定義一個thread-local變數的時候做初始化,初始化的值必須是一個常量表達式。
2。 __thread只能修飾POD型別,即不帶自定義的構造、複製、賦值、析構的型別,不能有non-static的protected或private成員,沒有基類和虛擬函式,因此對定義class做了很多限制。但可以改為修飾class指標型別便無需考慮此限制。
2:當執行緒變數是複雜的C++類變數時,即不能申明為_thread變數
執行緒變數對於其他執行緒是可見,同時我們可以延伸出例外一種方式來代替執行緒變數
ps:A是一個類,執行緒的數量為n
A a[n];
對每個執行緒對映一個ID,執行緒1只能訪問a[1],執行緒2訪問a[2],從而達到每個執行緒訪問一個對應的一個執行緒變數
二:多個執行緒共享一個資源
多個執行緒共享一個資源涉及多種方式:訊號量,互斥量,臨界區,自旋鎖,讀寫鎖,條件變數,CAS
1:訊號量
訊號量主要用於同步,訊號量在系統中可以被任意一個執行緒釋放
三個操作:
1、一個訊號量可以初始化為非負值
2、semWait操作可以使訊號量減1,若訊號量的值為負,則執行semWait的程序被阻塞。否則程序繼續執行。
3、semSignal操作使訊號量加1。若訊號量的值小於等於0,則被semWait操作阻塞的程序講被接觸阻塞。
ps: semWait對應P原語,semSignal對應V原語。
即A執行緒呼叫 semWait,B執行緒呼叫semSignal,可以釋放A執行緒,讓A執行緒執行
2:互斥量
互斥量主要用於防止多個執行緒同時訪問同一個資源
A執行緒加鎖了,B執行緒無法釋放A執行緒加的鎖,只能等A執行緒自己釋放
3:臨界區
在多程序程式中,臨界區申明的鎖,只對當前程序有效,其他程序無效,訊號量跟互斥鎖對其他程序也是有效的,可以獲取的
4:自旋鎖
自旋鎖加鎖時不會讓出cpu,一直會處於自旋狀態去獲取鎖,互斥量跟臨界區都是會進入休眠狀態,把CPU讓出,自旋鎖適用高效能場景,加鎖時間小於執行緒切換時間
5:讀寫鎖
當執行緒A處於讀的狀態,執行緒B也可以讀,但是不能寫,當執行緒A處於寫的狀態,執行緒B則不能讀,適用與少寫多讀的場景
6:條件變數
條件變數可以同時喚醒多個執行緒,訊號量只能喚醒一個,喚醒多個執行緒的時候,通常涉及到資源競爭,往往配合互斥鎖使用
7:CAS
CAS是個原子操作,即先比較相等再替換,這個時候會產生一個ABA問題,對於這個問題可以給資料加上一個version解決