執行緒同步 互斥量 Mutex 核心物件 CreateMutex
阿新 • • 發佈:2019-01-30
0、思考
1、相關api
CreateMutex
CreateMutexEx
OpenMutex
ReleaseMutex
CloseHandle
WaitForSingleObject
WaitForMultipleObjects
2、寫在前面
互斥量:確保一個執行緒獨佔對一個資源的訪問。(與關鍵程式碼段行為完全相同,只是互斥量屬於核心物件,關鍵程式碼段屬於使用者模式下的同步物件) 互斥量包含一個使用計數、執行緒id以及一個遞迴計數。(後面有用) 異常:假設執行緒試圖等待一個未觸發的互斥量物件。在這種情況下,執行緒通常會進入等待狀態。但是,系統要檢查想要獲取互斥物件的執行緒ID是否與互斥 物件內部記錄的執行緒ID相同。如果兩個執行緒ID相同,即使互斥物件處於未通知狀態,系統也允許該執行緒保持可排程狀態。
3、api說明
// // lpMutexAttributes:安全屬性。(通常為NULL) // bInitialOwner:互斥量初始狀態;觸發狀態(false),互斥量物件的執行緒id和遞迴計數都是0,不被任何執行緒佔用;未觸發狀態(true),物件執行緒 id將被設為呼叫執行緒的執行緒id,遞迴計數將被設為1。(通常為false) // lpName:核心物件名稱 WINBASEAPI __out_opt HANDLE WINAPI CreateMutexA( __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes, __in BOOL bInitialOwner, __in_opt LPCSTR lpName ); WINBASEAPI __out_opt HANDLE WINAPI CreateMutexW( __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes, __in BOOL bInitialOwner, __in_opt LPCWSTR lpName ); #ifdef UNICODE #define CreateMutex CreateMutexW #else #define CreateMutex CreateMutexA #endif // !UNICODE // dwFlags:0表示bInitialOwner的false,CREATE_MUTEX_INITIAL_OWNER表示true // dwDesiredAccess:訪問許可權 WINBASEAPI __out_opt HANDLE WINAPI CreateMutexExA( __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes, __in_opt LPCSTR lpName, __in DWORD dwFlags, __in DWORD dwDesiredAccess ); WINBASEAPI __out_opt HANDLE WINAPI CreateMutexExW( __in_opt LPSECURITY_ATTRIBUTES lpMutexAttributes, __in_opt LPCWSTR lpName, __in DWORD dwFlags, __in DWORD dwDesiredAccess ); #ifdef UNICODE #define CreateMutexEx CreateMutexExW #else #define CreateMutexEx CreateMutexExA #endif // !UNICODE // 釋放互斥量。 // hMutex:核心物件控制代碼 WINBASEAPI BOOL WINAPI ReleaseMutex( __in HANDLE hMutex ); // 訪問互斥量物件。(當訪問權執行緒不再需要訪問資源時,必須呼叫) // dwDesiredAccess:訪問許可權。(通常為SEMAPHORE_ALL_ACCESS) // bInheritHandle:繼承性。(通常為false) // lpName:核心物件名稱。 WINBASEAPI __out_opt HANDLE WINAPI OpenMutexA( __in DWORD dwDesiredAccess, __in BOOL bInheritHandle, __in LPCSTR lpName ); WINBASEAPI __out_opt HANDLE WINAPI OpenMutexW( __in DWORD dwDesiredAccess, __in BOOL bInheritHandle, __in LPCWSTR lpName ); #ifdef UNICODE #define OpenMutex OpenMutexW #else #define OpenMutex OpenMutexA #endif // !UNICODE
4、C++封裝
#pragma once
#include <windows.h>
class ncMutex
{
public:
ncMutex(LPCTSTR lpName = NULL)
{
_mutex = CreateMutex(NULL, False, lpName);
}
~ncMutex()
{
CloseHandle(_mutex);
}
public:
DWORD lock (DWORD timeout = INFINITE)
{
return WaitForSingleObject (_mutex, timeout);
}
BOOL unlock ()
{
return ReleaseMutex(_mutex);
}
private:
HANDLE _mutex;
};
5、順藤摸瓜
執行緒所有權:除了互斥量,沒有任何一個會記住自己是哪個執行緒等待成功的核心物件。(這使得在未觸發狀態下,也能為執行緒所獲得)
遺棄:如果佔用互斥量執行緒在釋放互斥量之前終止(使用ExitThread、TerminateThread、ExitProcess、TerminateProcess),由於佔用互斥量的執行緒
已經終止,因此無法釋放它。
因為系統會記錄所有的互斥量和執行緒核心物件,因此它確切知道互斥量何時被遺棄。當互斥量被遺棄時,系統會自動將互斥量物件的執行緒id和計數設為0,
然後檢查有沒有其他執行緒等待該互斥量。如果有,那麼系統會公平的選中一個正在等待的執行緒,把物件內部執行緒id設為所選執行緒id,計數設為1,這樣
被選擇執行緒變成可排程狀態,只是等待函式在此種情況返回WAIT_ABANDONED(只適用於互斥量)。