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;
}
posted @ 2017-08-16 14:52  caimagic  阅读(3264)  评论(0编辑  收藏  举报