經典執行緒同步 互斥量Mutex

2021-08-13 10:11:49 字數 4425 閱讀 5121

閱讀本篇之前推薦閱讀以下姊妹篇: 《

秒殺多執行緒第四篇乙個經典的多執行緒同步問題》

《秒殺多執行緒第五篇經典執行緒同步關鍵段cs》

《秒殺多執行緒第六篇經典執行緒同步事件event》

前面介紹了

關鍵段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

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

#include 

#include 

#include 

long

g_nnum;  

unsigned int

__stdcall fun(

void

*ppm);  

const

intthread_num = 10;  

//互斥量與關鍵段

handle

g_hthreadparameter;  

critical_section g_csthreadcode;  

intmain()  

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

#include 

#include 

#include 

const

char

mutex_name = 

"mutex_morewindows"

;  int

main()    

第二個程式:

[cpp]

view plain

copy

#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

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

》將介紹使用訊號量

semaphore

來解決這個經典執行緒同步問題。

如果覺得本文對您有幫助,『頂』支援一下,您的支援是我寫作最大的動力,謝謝。

多執行緒 同步 Mutex互斥量

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

Linux執行緒同步 互斥量 mutex

互斥量從本質上說就是一把鎖,提供對共享資源的保護訪問.1.初始化 在linux下,執行緒的互斥量資料型別是pthread mutex t.在使用前,要對它進行初始化 對於靜態分配的互斥量,可以把它設定為pthread mutex initializer,或者呼叫pthread mutex init....

C 執行緒同步互斥量Mutex

一 互斥物件 互斥物件屬於系統核心物件,它能夠使執行緒擁有對某個資源的絕對訪問權。互斥物件主要包含使用數量 執行緒id 遞迴計數器等。執行緒id表示當前擁有互斥物件的執行緒,遞迴計數器表示執行緒擁有互斥物件的次數。1 當互斥物件的執行緒id為0時,表示互斥物件不被任何執行緒所擁有,此時系統會發出該互...