【執行緒同步】臨界區與互斥量
Win32 中關於程序和執行緒的協調工作是由同步機制來完成的,同步機制相當於執行緒間的紅綠燈。
一. 同步和非同步
舉個例子:
PostMessage(),是把訊息放到對方的訊息佇列中,然後不管三七二十一,就回到原呼叫點繼續執行,這就是非同步。
SendMessage(),就像呼叫一般性函式,直到呼叫的函式結束,才會回到原點,這就是同步行為。
二. Critical Sections
如果一個執行緒已經進入某個臨界區,則另一個執行緒就絕不能夠進入同一個臨界區。
//初始化一個臨界區 VOID InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection // critical section ); //消除一個臨界區 VOID DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection // critical section ); //進入臨界區 VOID EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection // critical section ); //離開臨界區 VOID LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection // critical section ); 例如: CRITICAL_SECTION gCriticalSection; void Function() { InitializeCriticalSection(&gCriticalSection); EnterCriticalSection(&gCriticalSection); //Do something here LeaveCriticalSection(&gCriticalSection); DeleteCriticalSection(&gCriticalSection); }
一旦執行緒進入一個臨界區,則它就可以一再的重複進入該臨界區,當然每個進入操作都必須對應離開操作。
也就是EnterCriticalSection( ),可以巢狀。
但是千萬不要在臨界區中呼叫 sleep(),或任何 Wait..() 函式。
臨界區的缺點是:沒有辦法知道進入臨界區中的那個執行緒是生是死。如果那個執行緒在進入臨界區後當掉了,而且沒有退出來,那麼系統就沒有辦法消除掉此臨界區。
三. Mutexes
Mutexes 用途和 Critical Section 非常類似,執行緒擁有 mutex 就好象執行緒進入 critical section 一樣,但是它犧牲速度以增加彈性。
一旦沒有任何執行緒擁有那個 mutex,這個 mutex 便處於激發狀態
它與臨界區的區別是:
1. Mutexes 操作要比 Critical Section 費時的多。
2. Mutexes 可以跨程序使用,Critical Section 則只能在同一程序中使用。
3. 等待一個 Mutex 時,你可以指定"結束等待"的時間長度,而 Critical Section 則不行。
HANDLE CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, // 安全屬性,預設為NULL BOOL bInitialOwner, // initial owner LPCTSTR lpName // mutex 的名稱,是一個字串 ); //返回值:如果成功返回 handle,否則返回 NULL HANDLE OpenMutex( DWORD dwDesiredAccess, // access BOOL bInheritHandle, // inheritance option LPCTSTR lpName // object name ); //開啟一個已經存在的 mutex BOOL ReleaseMutex( HANDLE hMutex // handle to mutex ); //呼叫過程如下: CreateMutex(); //建立 WaitForXXXObject(); //等待 ReleaseMutex(); //釋放 CloseHandle(); //關閉
說明:
1. Mutex 的擁有權:
Mutex 的擁有權並非屬於那個產生它的執行緒,而是那個最後對些 Mutex 進行 WaitXXX() 操作並且尚未進行 ReleaseMutex() 操作的執行緒。
2. Mutex 被捨棄:
如果執行緒在結束前沒有呼叫 ReleaseMutex(),比如執行緒呼叫了 EXitThread() 或者因為當掉而結束。這時的 mutex 不會被摧毀,而是被視為"未被擁有"以及"未被激發"的狀態,在下一個 WaitXXX() 中執行緒會被以WAIT_ABANDONED_0 (WAIT_ABANDONED_0_n + 1 )來通知。
3. 最初擁有者:
CreateMutex(),第二個引數 bInitialOwner,允許你指定現行執行緒是否立刻擁有產生出來的 mutex。
如果沒有指定立刻擁有的情況:
HANDLE hMutex = CreateMutex(NULL, FALSE, "Sample Name");
int result = WaitForSingleObject(hMutex, INFINITE);
可能發生,在 CreateMutex 完成之後,發生了 context switch,執行權切換到另一個執行緒,那麼其它程序就有可能在 mutex 的產生者呼叫 WaitForSingleObject( ) 之前,鎖住這個 mutex 物件。
原文:https://blog.csdn.net/lwbeyond/article/details/7617234