具有允許相互排斥(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 後面那個才是呼叫拷貝賦值,拷貝賦值是對已...