Windows編程-- 線程和核心對象的同步 - 互斥對象核心對象

來源:互聯網
上載者:User

互斥對象(mutex核心對象能夠確保線程擁有對單個資源的互斥訪問權。

互斥對象包含一個使用數量,一個線程ID和一個遞迴計數器。

互斥對象的行為特性與關鍵程式碼片段相同,但是互斥對象屬於核心對象,而關鍵程式碼片段則屬於使用者方式對象。

這意味著互斥對象的運行速度比關鍵程式碼片段要慢。但是這也意味著不同進程中的多個線程能夠訪問單個互斥對象,並且這意味著線程在等待訪問資源時可以設定一個逾時值。

ID用於標識系統中的哪個線程當前擁有互斥對象,

遞迴計數器用於指明該線程擁有互斥對 象的次數。

作用:

通常來說,它們用於保護由多個線程訪問的記憶體塊。如果多個線程要同時訪問記憶體塊,記憶體塊中的資料就可能遭到破壞。互斥對象能夠保證訪問記憶體塊的任何線程擁有對該記憶體塊的獨佔訪問權,這樣就能夠保證資料的完整性。

 

互斥對象的使用規則如下:

• 如果線程ID是0(這是個無效ID),互斥對象不被任何線程所擁有,並且發出該互斥對象的通知訊號。   

• 如果I D是個非0數字,那麼一個線程就擁有互斥對象,並且不發出該互斥對象的通知訊號。

• 與所有其他核心對象不同, 互斥對象在作業系統中擁有特殊的代碼,允許它們違反正常的規則。

 

若要使用互斥對象,必須有一個進程首先調用CreateMutex,以便建立互斥對象:

 

HANDLE CreateMutex(
PSECURITY_ATTRIBUTES psa,
BOOLfInitialOwner,
PCTSTRpszName);

 

 

 

psa和pszName參數是核心對象的安全屬性和核心對象的命名,

fInitialOwner參數用於控制互斥對象的初始狀態。

如果傳遞FALSE(這是通常情況下傳遞的值),那麼互斥對象的ID和遞迴計數器均被設定為0。這意味著該互斥對象沒有被任何線程所擁有,因此要發出它的通知訊號

如果傳遞TRUE,那麼該對象的線程ID被設定為調用線程的ID,遞迴計數器被設定為1。由於ID是個非0數字,因此該互斥對象開始時不發出通知訊號

 

通過調用OpenMutex,另一個進程可以獲得它自己進程與現有互斥對象相關的控制代碼:

 

HANDLE OpenMutex(
DWORDfdwAccess,
BOOLbInheritHandle,
PCTSTRpszName);

 

 

 

通過調用一個等待函數,並傳遞負責保護資源的互斥對象的控制代碼,線程就能夠獲得對共用資源的訪問權。在內部,等待函數要檢查線程的ID,以瞭解它是否是0(互斥對象發出通知訊號)。

如果線程ID是0,那麼該線程ID被設定為調用線程的ID,遞迴計數器被設定為1,同時,調用線程保持可調度狀態。

如果等待函數發現ID不是0(不發出互斥對象的通知訊號),那麼調用線程便進入等待狀態。系統將記住這個情況,並且在互斥對象的I D重新設定為0時,將線程ID設定為等待線程的I D,將遞迴計數器設定為1,並且允許等待線程再次成為可調度線程。與所有情況一樣,對互斥核心對象進行的檢查和修改都是以原子操作方式進行的。

 

異常規則

對於互斥對象來說,正常的核心對象的已通知和未通知規則存在一個特殊的異常情況。

比如說,一個線程試圖等待一個未通知的互斥對象。在這種情況下,該線程通常被置於等待狀態。然而,系統要查看試圖擷取互斥對象的線程的I D是否與互斥對象中記錄的線程I D相同。如果兩個線程I D相同,即使互斥對象處於未通知狀態,系統也允許該線程保持可調度狀態。我們不認為該“異常”行為特性適用於系統中的任何地方的其他核心對象。每當線程成功地等待互斥對象時,該對象的遞迴計數器就遞增。若要使遞迴計數器的值大於1,唯一的方法是線程多次等待相同的互斥對象,以便利用這個異常規則。

 

一旦線程成功地等待到一個互斥對象,該線程就知道它已經擁有對受保護資源的獨佔訪問權。試圖訪問該資源的任何其他線程(通過等待相同的互斥對象)均被置於等待狀態中。當目前擁有對資源的訪問權的線程不再需要它的訪問權時,它必須調用ReleaseMutex函數來釋放該互斥對象:

 

BOOL ReleaseMutex(HANDLE hMutex);

 

 


該函數將對象的遞迴計數器遞減1。如果線程多次成功地等待一個互斥對象,在互斥對象的遞迴計數器變成0之前,該線程必須以同樣的次數調用ReleaseMutex函數。當遞迴計數器到達0時,該線程ID也被置為0,同時該對象變為已通知狀態。

 

當該對象變為已通知狀態時,系統要查看是否有任何線程正在等待互斥對象。如果有,系統將“按公平原則”選定等待線程中的一個,為它賦予互斥對象的所有權。當然,這意味著線程I D被設定為選定的線程的ID,並且遞迴計數器被置為1。如果沒有其他線程正在等待互斥對象,那麼該互斥對象將保持已通知狀態,這樣,等待互斥對象的下一個線程就立即可以得到互斥對象。

 

釋放問題

互斥對象不同於所有其他核心對象,因為互斥對象有一個“線程所有權”的概念。本章介紹的其他核心對象中,沒有一種對象能夠記住哪個線程成功地等待到該對象,只有互斥對象能夠對此保持跟蹤。互斥對象的線程所有權概念是互斥對象為什麼會擁有特殊異常規則的原因,這個異常規則使得線程能夠擷取該互斥對象,儘管它沒有發出通知。

 

這個異常規則不僅適用於試圖擷取互斥對象的線程,而且適用於試圖釋放互斥對象的線程。當一個線程調用ReleaseMutex函數時,該函數要查看調用線程的ID是否與互斥對象中的線程ID相匹配。如果兩個ID相匹配,遞迴計數器就會像前面介紹的那樣遞減。如果兩個線程的ID不匹配,那麼ReleaseMutex函數將不進行任何操作,而是將FA LSE(表示失敗)返回給調用者。此時調用GetLastError,將返回ERROR_NOT_OWNER(試圖釋放不是調用者擁有的互斥對象)。

 

因此,如果在釋放互斥對象之前,擁有互斥對象的線程終止運行(使用ExitThread、TerminateThread、ExitProcess或TerminateProcess函數),那麼互斥對象和正在等待互斥對象的其他線程將會發生什麼情況呢?答案是,系統將把該互斥對象視為已經被放棄——擁有互斥對象的線程決不會釋放它,因為該線程已經終止運行。

 

由於系統保持對所有互斥對象和線程核心對象的跟蹤,因此它能準確的知道互斥對象何時被放棄。當一個互斥對象被放棄時,系統將自動把互斥對象的I D複置為0,並將它的遞迴計數器複置為0。然後,系統要查看目前是否有任何線程正在等待該互斥對象。如果有,系統將“公平地”選定一個等待線程,將I D設定為選定的線程的I D,並將遞迴計數器設定為1,同時,選定的線程變為可調度線程。

 

這與前面的情況相同,差別在於等待函數並不將通常的WA I T _ OBJECT_0值返回給線程。相反,等待函數返回的是特殊的WAIT_ABANDONED值。這個特殊的傳回值(它只適用於互斥對象)用於指明線程正在等待的互斥對象是由另一個線程擁有的,而這另一個線程已經在它完成對共用資源的使用前終止運行。(FangSH註: 就像被遺棄。有的等待,有的中途放棄。結果都沒有被用到)這不是可以進入的最佳情況。新調度的線程不知道目前資源處於何種狀態,也許該資源已經完全被破壞了。在這種情況下必須自己決定應用程式應該怎麼辦。

在實際運行環境中,大多數應用程式從不明確檢查WAIT_ABANDONED傳回值,因為線程很少是剛剛終止運行(上面介紹的情況提供了另一個例子,說明為什麼決不應該調用TerminateThread函數)。

 

互斥對象與關鍵程式碼片段的比較

就等待線程的調度而言,互斥對象與關鍵程式碼片段之間有著相同的特性。但是它們在其他屬性方面卻各不相同。表對它們進行了各方面的比較。

表9-1 互斥對象與關鍵程式碼片段的比較

特性

互斥對象

關鍵程式碼片段

運行速度

是否能夠跨進程邊界來使用

聲明

HANDLE hmtx;

CRITICAL_SECTION cs;

初始化

hmtx = CreateMutex(NULL,FALSE,NULL);

InitializeCriticalSection(&es );

清除

CloseHandle(hmtx);

DeleteCriticalSection(&cs);

無限等待

WaitForSingleObject(hmtx , INFINITE);

EnterCriticalSection(&cs);

0等待

WaitForSingleObjectTry(hmtx , 0);

EnterCriticalSection(&cs);

任意等待

WaitForSingleObject(hmtx , dw Milliseconds);

不能

釋放

ReleaseMutex(hmtx);

LeaveCriticalSection(&cs);

是否能夠等待其他核心對象

是(使用WaitForMultipleObjec ts或類似的函數)

 

 

FangSH  2011-01-04

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.