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);

能否被一道用于等待其他内核对象

可以(使用WaitForMultipleObjectsWaitForMultipleObjectsExMsgWaitForMultipleObjects MsgWaitForMultipleObjectsEx等等

不可

当拥有锁的线程死亡时

Mutex变成abandoned状态,其他的等待线程可以获得锁。

Critical Section的状态不可知(undefined),以后的动作就不能保证了。

自己会不会锁住自己

不会(对已获得的Mutex,重复调用WaitForSingleObject不会锁住自己。但最后你别忘了要调用同样次数的ReleaseMutex

不会(对已获得的Critical Section,重复调用EnterCriticalSection不会锁住自己。但最后你别忘了要调用同样次数的LeaveCriticalSection

 

下面是一些补充:

l         请先检查你的设计,把不必要的全局或共享对象改为局部对象。全局的东西越少,出问题的可能就越小。

l         每次你使用EnterCriticalSection时,请不要忘了在函数的所有可能返回的地方都加上LeaveCriticalSection。对于Mutex也同样。若你把这个问题和Win32 structured exceptionC++ 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         根据你的互斥范围需求的不同,把MutexCritical Section定义为类的成员变量,或者静态类变量。

l         若你想限制访问的全局变量只有一个而且类型比较简单(比如是LONGPVOID型),你也可以使用InterlockedXXX系列函数来保证一个线程写多个线程读。

 

 

本文主要参照了Jeffrey Richter的《Programming Applications for Microsoft Windows, 4th Ed.》。

专注于企业信息化,最近对股票数据分析较为感兴趣,可免费分享股票个股主力资金实时变化趋势分析工具,股票交流QQ群:457394862

本文转自沧海-重庆博客园博客,原文链接:http://www.cnblogs.com/omygod/archive/2006/11/08/554524.html,如需转载请自行联系原作者
目录
相关文章
|
前端开发 测试技术 Go
嵌套结构体导出excel的实现方式
嵌套结构体导出excel的实现方式
195 0
|
Web App开发 移动开发 前端开发
巧用 display: contents 增强页面语义
巧用 display: contents 增强页面语义
391 1
SAP MM初阶之没有定义Access Sequence的条件类型不能使用MEK1维护条件记录
SAP MM初阶之没有定义Access Sequence的条件类型不能使用MEK1维护条件记录
SAP MM初阶之没有定义Access Sequence的条件类型不能使用MEK1维护条件记录
SAP MM 条件类型中PB00的‘Group Cond.‘标记的作用?
SAP MM 条件类型中PB00的‘Group Cond.‘标记的作用?
SAP MM 条件类型中PB00的‘Group Cond.‘标记的作用?
|
程序员
Attribute(特性),怎么用才更好? —— 字段编号被误解了
  上一篇里(Attribute(特性),怎么用才更好? ),有人说,“坚决杜绝magic number ”,这个magic number指的就是字段编号吧,其实您误解了。   一提到字段编号,可能有些人的第一反应就是这样的用法:     Person1.2000020,或者Person1[2000020],或者ds[2000020]。
901 0
|
图形学 开发者
Unity LOD-Level of Detail(多层次细节)用法教程
Unity LOD 多层次细节 本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) Chinar ——...
2583 0
|
Linux C语言
利用__attribute__((section()))构建初始化函数表【转】
转自: https://mp.weixin.qq.com/s?__biz=MzAwMDUwNDgxOA==&mid=2652663356&idx=1&sn=779762953029c0e0946c22ef2bb0b754&chksm=810f28a1b678a1b747520ba3ee47c9e...
1759 0