多執行緒之七 經典執行緒同步 互斥量Mutex

2021-06-06 11:23:16 字數 4229 閱讀 4252

前面介紹了

關鍵段cs

、事件event

在經典執行緒同步問題

中的使用。本篇介紹用互斥量mutex

來解決這個問題。

互斥量也是乙個核心物件,它用來確保乙個執行緒獨佔乙個資源的訪問。互斥量與關鍵段的行為非常相似,並且互斥量可以用於不同程序中的執行緒互斥訪問資源。使用互斥量mutex

主要將用到四個函式。下面是這些函式的原型和使用說明。

第乙個createmutex

函式功能:建立互斥量(注意與事件event

的建立函式對比)

函式原型:

handle

createmutex(

lpsecurity_attributes

lpmutexattributes,

bool

binitialowner

,     

lpctstr

lpname );

函式說明:

第乙個引數表示安全控制,一般直接傳入

null

。第二個引數用來確定互斥量的初始擁有者。如果傳入

true

表示互斥量物件內部會記錄建立它的執行緒的執行緒

id號並將遞迴計數設定為

1,由於該執行緒

id非零,所以互斥量處於未觸發狀態。如果傳入

false

,那麼互斥量物件內部的執行緒

id號將設定為

null

,遞迴計數設定為

0,這意味互斥量不為任何執行緒占用,處於觸發狀態。

第三個引數用來設定互斥量的名稱,在多個程序中的執行緒就是通過名稱來確保它們訪問的是同乙個互斥量。

函式訪問值:

成功返回乙個表示互斥量的控制代碼,失敗返回null。  

第二個開啟互斥量

函式原型:

handle

openmutex(

dword

dwdesiredaccess,

bool

binherithandle,

lpctstr

lpname     //名稱 );

函式說明:

第乙個引數表示訪問許可權,對互斥量一般傳入

mutex_all_access。詳細解釋可以檢視msdn文件。

第二個引數表示互斥量控制代碼繼承性,一般傳入true即可。

第三個引數表示名稱。某乙個程序中的執行緒建立互斥量後,其它程序中的執行緒就可以通過這個函式來找到這個互斥量。

函式訪問值:

成功返回乙個表示互斥量的控制代碼,失敗返回null。  

第三個觸發互斥量

函式原型:

bool

releasemutex

(handle

hmutex)

函式說明:

訪問互斥資源前應該要呼叫等待函式,結束訪問時就要呼叫releasemutex()來表示自己已經結束訪問,其它執行緒可以開始訪問了。

最後乙個清理互斥量

由於互斥量是核心物件,因此使用closehandle()就可以(這一點所有核心物件都一樣)。  

[cpp]view plain

copy

print?

//經典執行緒同步問題 互斥量mutex

#include 

#include 

#include 

long g_nnum;  

unsigned int __stdcall fun(void *ppm);  

const

int thread_num = 10;  

//互斥量與關鍵段

handle  g_hthreadparameter;  

critical_section g_csthreadcode;  

int main()  

waitformultipleobjects(thread_num, handle, true, infinite);  

//銷毀互斥量和關鍵段

closehandle(g_hthreadparameter);  

deletecriticalsection(&g_csthreadcode);  

for (i = 0; i 

closehandle(handle[i]);  

return 0;  

}  unsigned int __stdcall fun(void *ppm)    

執行結果如下圖:

可以看出,

與關鍵段類似,互斥量也是不能解決執行緒間的同步問題。

聯想到關鍵段會記錄執行緒

id即有「執行緒擁有權」的,而互斥量也記錄執行緒

id,莫非它也有「執行緒擁有權」這一說法。

答案確實如此,互斥量也是有「執行緒擁有權」概念的。「執行緒擁有權」在

關鍵段中有詳細的說明,這裡就不再贅述了。另外由於互斥量常用於多程序之間的執行緒互斥,所以它比關鍵段還多乙個很有用的特性——「遺棄」情況的處理。比如有乙個占用互斥量的執行緒在呼叫

releasemutex

()觸發互斥量前就意外終止了(相當於該互斥量被「遺棄」了),那麼所有等待這個互斥量的執行緒是否會由於該互斥量無法被觸發而陷入乙個無窮的等待過程中了?這顯然不合理。因為占用某個互斥量的執行緒既然終止了那足以證明它不再使用被該互斥量保護的資源,所以這些資源完全並且應當被其它執行緒來使用。因此在這種「遺棄」情況下,系統自動把該互斥量內部的執行緒

id設定為

0,並將它的遞迴計數器復置為

0,表示這個互斥量被觸發了。然後系統將

「公平地

」選定乙個等待執行緒來完成排程(被選中的執行緒的

waitforsingleobject()會返回wait_abandoned_0)。

下面寫二個程式來驗證下:

第乙個程式建立互斥量並等待使用者輸入後就觸發互斥量。第二個程式先開啟互斥量,成功後就等待並根據等待結果作相應的輸出。詳見**:

第乙個程式:

[cpp]view plain

copy

print?

#include 

#include 

#include 

const

char mutex_name = "mutex_morewindows";  

int main()    

第二個程式:

[cpp]view plain

copy

print?

#include 

#include 

const

char mutex_name = "mutex_morewindows";  

int main()  

printf("等待中....\n");  

dword dwresult = waitforsingleobject(hmutex, 20 * 1000); //等待互斥量被觸發

switch (dwresult)  

closehandle(hmutex);  

return 0;  

}  

運用這二個程式時要先啟動程式一再啟動程式二。下面展示部分輸出結果:

結果一.

二個程序順利執行完畢:

結果二.將程式一中//exit(0);前面的注釋符號去掉,這樣程式一在觸發互斥量之前就會因為執行

exit(0);語句而且退出,程式二會收到

wait_abandoned

訊息並輸出「

擁有互斥量的程序意外終止

有這個對「遺棄」問題的處理,在多程序中的執行緒同步也可以放心的使用互斥量。  

最後總結下互斥量mutex

1

.互斥量是核心物件,它與關鍵段都有「執行緒所有權」所以不能用於執行緒的同步。

2

.互斥量能夠用於多個程序之間執行緒互斥問題,並且能完美的解決某程序意外終止所造成的「遺棄」問題。

多執行緒之Mutex 互斥量

include include include long g count 0 long g sum 0 static const int g s count 10 critical section g csthreadparamer critical section g csthreadcode h...

經典執行緒同步 互斥量Mutex

閱讀本篇之前推薦閱讀以下姊妹篇 秒殺多執行緒第四篇乙個經典的多執行緒同步問題 秒殺多執行緒第五篇經典執行緒同步關鍵段cs 秒殺多執行緒第六篇經典執行緒同步事件event 前面介紹了 關鍵段cs 事件event 在經典執行緒同步問題 中的使用。本篇介紹用互斥量mutex 來解決這個問題。互斥量也是乙個...

多執行緒 同步 Mutex互斥量

建立互斥量 handle createmutex lpsecurity attributes lpmutexattributes,安全性 bool binitialowner,true 建立執行緒擁有互斥量,false 相反 lpctstr lpname 執行緒名字,如果為null表示匿名,否則為命...