Mutex 和 Critical Section 的異同

Mutex 和 Critical Section 的異同

MutexCritical Section都是主要用於限制多線程(Multithread)對全局或共享的變量、對象或內存空間的訪問。下面是其主要的異同點(不同的地方用綠色表示)。

 

Mutex

Critical Section

性能和速度

慢。

Mutex 是內核對象,相關函數的WaitForSingleObject

ReleaseMutex)需要用戶模式(User Mode)到內核模式(Kernel Mode)的轉換,在x86處理器上這種轉化一般要發費600個左右的 CPU指令週期。

快。

Critical Section本身不是內核對象,相關函數(EnterCriticalSectionLeaveCriticalSection)的調用一般都在用戶模式內執行,在x86處理器上一般只需要發費9個左右的 CPU指令週期。只有當想要獲得的鎖正好被別的線程擁有時纔會退化成和Mutex一樣,即轉換到內核模式,發費600個左右的 CPU指令週期。

能否跨越進程(Process)邊界

可以

不可

定義寫法

HANDLE hmtx;

CRITICAL_SECTION cs;

初始化寫法

hmtx= CreateMutex (NULL, FALSE, NULL);

InitializeCriticalSection(&cs);

結束清除寫法

CloseHandle(hmtx);

DeleteCriticalSection(&cs);

無限期等待的寫法

WaitForSingleObject (hmtx, INFINITE);

EnterCriticalSection(&cs);

0等待(狀態檢測)的寫法

WaitForSingleObject (hmtx, 0);

TryEnterCriticalSection(&cs);

任意時間等待的寫法

WaitForSingleObject (hmtx, dwMilliseconds);

不支持

鎖釋放的寫法

ReleaseMutex(hmtx);

LeaveCriticalSection(&cs);

能否被一道用於等待其他內核對象

可以(使用WaitForMultipleObjectsWaitForMultipleObjectsExMsgWaitForMultipleObjectsMsgWaitForMultipleObjectsEx等等

不可

當擁有鎖的線程死亡時

Mutex變成abandoned狀態,其他的等待線程可以獲得鎖。

Critical Section的狀態不可知(undefined),以後的動作就不能保證了。

自己會不會鎖住自己

不會(對已獲得的Mutex,重複調用WaitForSingleObject不會鎖住自己。但最後你別忘了要調用同樣次數的ReleaseMutex

不會(對已獲得的Critical Section,重複調用EnterCriticalSection不會鎖住自己。但最後你別忘了要調用同樣次數的LeaveCriticalSection

 

下面是一些補充:

l         請先檢查你的設計,把不必要的全局或共享對象改爲局部對象。全局的東西越少,出問題的可能就越小。

l         每次你使用EnterCriticalSection時,請不要忘了在函數的所有可能返回的地方都加上LeaveCriticalSection。對於Mutex也同樣。若你把這個問題和Win32 structured exception或C++ exception一起考慮,你會發現問題並不是那麼簡單。自定義一個封裝類可能是一種解決方案,以Critical Section爲例的代碼如下所示:

class csholder

{

    CRITICAL_SECTION *cs;

public:

    csholder(CRITICAL_SECTION *c): cs(c)

    { EnterCriticalSection(cs); }

    ~csholder() { LeaveCriticalSection(cs); }

};

 

CRITICAL_SECTION some_cs;

void foo()

{

    // ...

    csholder hold_some(&some_cs);

 

    // ... CS protected code here

 

    // at return or if an exception happens

    // hold_some's destructor is automatically called

}

l         根據你的互斥範圍需求的不同,把Mutex或Critical Section定義爲類的成員變量,或者靜態類變量。

l         若你想限制訪問的全局變量只有一個而且類型比較簡單(比如是LONG或PVOID型),你也可以使用InterlockedXXX系列函數來保證一個線程寫多個線程讀。

 

createMutex();

OpenMutex();

ReleaseMutex();

CloseMutex();

         如果你創建的Mutex已經被使用(Mutex已經被創建),則CreateMutex()返回的是指向已經存在的那個Mutex的句柄,此時調用GetLastError()會獲得ERROR_ALREADY_EXISTS   的通知,表示Mutex已經存在!而如果Mutex未被創建過,則返回NULL。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章