Mutex 和 Critical Section 的异同

 
Mutex和Critical Section都是主要用于限制多线程(Multithread)对全局或共享的变量、对象或内存空间的访问。下面是其主要的异同点(不同的地方用绿色表示)。
 
Mutex
Critical Section
性能和速度
慢。
Mutex 是内核对象,相关函数的 WaitForSingleObject
ReleaseMutex )需要用户模式( 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 WaitForMultipleObjects Ex Msg WaitForMultipleObjects Msg WaitForMultipleObjects Ex 等等
不可
当拥有锁的线程死亡时
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 f oo ()
{
    // ...
    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系列函数来保证一个线程写多个线程读。
 
 
本文主要参照了Jeffrey Richter的《Programming Applications for Microsoft Windows, 4 th Ed.》。
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值