C 11多執行緒學習筆記(2) mutex

2021-09-29 11:36:03 字數 3898 閱讀 2125

具有允許相互排斥(mutex)併發執行關鍵**段的功能的標頭,從而可以顯式避免資料爭用。它包含mutex型別,lock型別和其他函式:

禁止拷貝與移動構造,只有預設建構函式,通過其建立的mutex物件處於unlock狀態。

通過mutex物件呼叫lock()函式,可以鎖住mutex物件,有三種情況:

1) 該互斥量未被上鎖,則lock()會成功將其上鎖並返回繼續執行。

2) 該互斥量被其他執行緒上鎖,則lock()會保持本執行緒阻塞,直到成功獲取到該互斥量並上鎖後返回。

3) 該互斥量已被本執行緒鎖定,則會陷入死鎖。

釋放對互斥量的所有權,即變為「未獲得鎖」的狀態。(通常mutex物件用於對lock物件的構造,這裡指lock物件回歸未獲得鎖的狀態)

通過mutex物件呼叫try_lock()函式,嘗試鎖住mutex物件,有三種情況:

1) 該互斥量未被上鎖,則try_lock()會成功上鎖並返回繼續執行。

2) 該互斥量已經被其他執行緒上鎖,則try_lock()會返回false(不會產生阻塞)。

3) 該互斥量已經被本執行緒上鎖,則會陷入死鎖。

【例3】

#include

#include

#include

#include

#include

using

namespace std;

mutex mtx;

string str =

"buwangchuxin,"

;void

func1

(string _str)

void

func2

(string _str)

intmain()

return0;

}//執行結果:

//結果1:buwangchuxin,laojishiming laojishiming

//結果2:buwangchuxin,laojishiming laojishiming

本例中,由於func1、func2中對互斥量上鎖,使得func1、func2可以獨佔對全域性變數str的訪問、修改的權利,他們分別處於th1與th2執行緒中,由於cpu搶占策略,兩個執行緒的先後在各次除錯時會有差別,但是結果是比較符合預期的,沒有出現亂碼的情況,而如果沒有加鎖,則會出現亂碼,因為func1與func2都有對字串的擴充套件操作,兩線程同時對同一塊記憶體區修改,容易產生不期望的結果。

對於成對地使用mutex物件呼叫lock與unlock雖然可以實現上鎖與解鎖,但是在本執行緒多次對同一互斥量上鎖無疑會造成死鎖的問題,實際的需求若比較複雜,需要逐層對互斥量上鎖再逐層解鎖(遞迴互斥),可以考慮使用recursive_mutex物件。只有預設建構函式,移動構造和其他複製操作都被刪除。

#include

#include

#include

#include

using

namespace std;

class

test

size_t add

(size_t val)

size_t increment()

};test c;

void

change_out()

intmain()

//輸出結果:每1秒列印 count=i\n

相比起 mutex物件,recursive_mutex物件在多次鎖定和解鎖上顯示出新的特性,但依舊是手動鎖定,不夠方便。

以類似 mutex 的行為, timed_mutex 提供排他性非遞迴所有權語義。另外, timed_mutex 提供通過 try_lock_for 和 try_lock_until 方法試圖帶時限地要求 timed_mutex 所有權的能力。

預設建構函式,operator = 與move都被刪除。

template

<

class

rep,

class

period

>

bool

try_lock_for

(const std::chrono::duration

& timeout_duration )

;

嘗試獲取鎖,並允許為此等待 timeout_duration這一時長(形成阻塞),獲得鎖或時長耗盡都可以使函式返回,取決於哪個先來。但如果 timeout_duration小於等於 timeout_duration.zero即少於0秒,則此函式等同於 try_lock。如果成功獲取鎖,則立刻上鎖並返回 true;在時長內若互斥量被其他執行緒鎖住則繼續等待,被本執行緒鎖住則陷入死鎖;超時即代表獲取鎖失敗並返回 false。

如果返回 true,則同一互斥量在本函式呼叫之前的,所呼叫的unlock與本次鎖定同步。重複呼叫try_lock_for的行為未被定義。

【例5】

#include

#include

#include

#include

#include

using

namespace std;

mutex cout_mutex;

timed_mutex mutex;

void

job(

int id)

else

stream <<

"failed "

; this_thread::

sleep_for

(std::chrono::

milliseconds

(100))

;}cout_mutex.

lock()

; cout <<

"["<< id <<

"] "

<< stream.

str(

)<<

"\n"

; cout_mutex.

unlock()

;}intmain()

//可能的輸出:

//[0] failed failed failed

//[3] failed failed success

//[2] failed success failed

//[1] success failed success

template

<

class

clock

,class

duration

>

bool

try_lock_until

(const std::chrono::time_point

&

#include

#include

#include

#include

std::timed_mutex test_mutex;

voidf(

)int

main()

//阻塞10秒

以類似 std::recursive_mutex 的方式, recursive_timed_mutex 提供排他性遞迴所有權語義。另外, recursive_timed_mutex 通過 try_lock_for 與 try_lock_until ,提供帶時限地試圖要求 recursive_timed_mutex 所有權的能力。

簡單來講,recursive_timed_mutex是在timed_mutex基礎上擴充套件生成了遞迴的特性。

基本可鎖定量,要求物件滿足可以呼叫lock()與unlock(),包括:

可鎖定量,要求滿足物件可以呼叫try_lock(),包括:

定時鎖定量,要求滿足物件可以呼叫try_lock_for()與try_lock_until(),包括:

C 11多執行緒(2)

多執行緒的建立方法 一 函式指標形式 將執行緒函式的函式名 函式指標 作為執行緒物件的引數進行建立執行緒,如果執行緒函式有引數,將引數按順序傳入執行緒物件,如下所示 三 lamda函式 include include using namespace std int main cout main th...

C 11多執行緒學習筆記(一)

程序 英語 process 是指計算機中已執行的程式。程序曾經是分時系統的基本運作單位。執行緒 英語 thread 是作業系統能夠進行運算排程的最小單位。大部分情況下,它被包含在程序之中,是程序中的實際運作單位。一條執行緒指的是程序中乙個單一順序的控制流,乙個程序中可以併發多個執行緒,每條執行緒並行...

c 11多執行緒課堂筆記

4 諸如 int a a 1 char a a a 這種寫法是錯的,空位址不能賦值 5 char aa char asd 這是可以的 6 student s4 s3 呼叫的是拷貝構造!並非拷貝賦值,因為這是建立物件 7 student s4 s3 s4 s1 後面那個才是呼叫拷貝賦值,拷貝賦值是對已...