zoukankan      html  css  js  c++  java
  • 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 
    ");
    
    	LeaveCriticalSection(&g_cs);
    	return 0;
    }
    
    LRESULT WINAPI ReadThread(PVOID arg)
    {
    	EnterCriticalSection(&g_cs);
    
    	printf("ReadThread 
    ");
    
    	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 
    ");
    
    	ReleaseMutex(hMutex);
    	return 0;
    }
    
    LRESULT WINAPI ReadThread2(PVOID arg)
    {
    	WaitForSingleObject(hMutex, INFINITE);
    
    	printf("ReadThread2 
    ");
    
    	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;
    }
    
  • 相关阅读:
    HDU 1501 Zipper(DFS)
    HDU 2181 哈密顿绕行世界问题(DFS)
    HDU 1254 推箱子(BFS)
    HDU 1045 Fire Net (DFS)
    HDU 2212 DFS
    HDU 1241Oil Deposits (DFS)
    HDU 1312 Red and Black (DFS)
    HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
    HDU 1022 Train Problem I(栈)
    HDU 1008 u Calculate e
  • 原文地址:https://www.cnblogs.com/langzou/p/7373356.html
Copyright © 2011-2022 走看看