windows 下 Mutex和Critical Section 區別和使用


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

Mutex Critical Section
性能和速度 慢。Mutex 是內核對象,相關函數的執行 (WaitForSingleObject,eleaseMutex)需要用戶模式(User Mode)到內核模式(Kernel Mode)的轉換,在x86處理器上這種轉化一般要發費600個左右的 CPU指令周期 快,Critical Section本身不是內核對象,相關函數(EnterCriticalSection,LeaveCriticalSection)的調用一般都在用戶模式內執行,在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);
能否被一道用於等待其他內核對象 可以(使用WaitForMultipleObjects,WaitForMultipleObjectsEx,MsgWaitForMultipleObjects,MsgWaitForMultipleObjectsEx等等) 不可
當擁有鎖的線程死亡時 Mutex變成abandoned狀態,其他的等待線程可以獲得鎖 CriticalSection的狀態不可知(undefined),以后的動作就不能保證了。

有人測試結果,CriticalSection用時速度比Mutex快不少。
http://blog.csdn.net/dreamfreelancer/article/details/4237272
windows下100萬次加/解鎖測試:
CriticalSection用時:31ms
Mutex用時:953ms
結論:CriticalSection性能遠遠高於Mutex(高出約30倍)。因此,在能用CriticalSection時絕不用Mutex,當然,后者可命名,而前者不行,因此,Mutex可用於進程間通信,但CriticalSection通常只能用於線程間通信。
另外,Windows上Mutex和CriticalSection都是缺省Recursive的(且不能被改變,如要實現non-recursive互斥,得用Semophore),就是同一線程在獲得鎖后,再次加鎖不會導致阻塞,這在Linux下需要指定。 但Mutex和CriticalSection行為還是存在差異,如果在同一線程內進行了Recursive的加,解鎖操作,若因為程序錯誤導致解鎖操作次數比加鎖操作多,對於Mutex,這不會有任何問題(linux和Windows都是如此),但CriticalSection表現卻不同,多於必要的Unlock操作會導致下次Lock操作被阻塞。

Demo code CRITICAL_SECTION

#include <windows.h>   
#include "stdio.h"

CRITICAL_SECTION g_cs;

LRESULT WINAPI WriteThread(PVOID arg)
{
	EnterCriticalSection(&g_cs);

	printf("WriteThread \n");

	LeaveCriticalSection(&g_cs);
	return 0;
}

LRESULT WINAPI ReadThread(PVOID arg)
{
	EnterCriticalSection(&g_cs);

	printf("ReadThread \n");

	LeaveCriticalSection(&g_cs);
	return 0;
}


int main1()
{
	HANDLE hThreadArray[2];
	InitializeCriticalSection(&g_cs);

	hThreadArray[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WriteThread, NULL, 0, NULL);
	hThreadArray[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReadThread, NULL, 0, NULL);

	WaitForMultipleObjects(2, hThreadArray, TRUE, INFINITE);

	DeleteCriticalSection(&g_cs);
	getchar();

	return 0;
}

Demo code Mutex

#include <windows.h>   
#include "stdio.h"

HANDLE hMutex = NULL;

LRESULT WINAPI WriteThread2(PVOID arg)
{
	WaitForSingleObject(hMutex, INFINITE);

	printf("WriteThread2 \n");

	ReleaseMutex(hMutex);
	return 0;
}

LRESULT WINAPI ReadThread2(PVOID arg)
{
	WaitForSingleObject(hMutex, INFINITE);

	printf("ReadThread2 \n");

	ReleaseMutex(hMutex);
	return 0;
}


int main()
{
	HANDLE hThreadArray[2];

	hMutex = CreateMutex(NULL, FALSE, NULL);

	hThreadArray[0] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WriteThread2, NULL, 0, NULL);
	hThreadArray[1] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ReadThread2, NULL, 0, NULL);

	WaitForMultipleObjects(2, hThreadArray, TRUE, INFINITE);

	getchar();
	CloseHandle(hMutex);

	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM