您的位置:首页 > 其它

互斥、临界区、信号灯、事件

2008-02-16 16:23 204 查看
互斥,每次只能有一个线程可以通过Wait

信号灯,最多只能同时有N个线程可以通过Wait

临界区,每次只能一个线程可以通过Enter

事件。。。通过Wait来进行判定时间的发生

令:摘抄了葡萄架上的牵牛花同志的BLOG里对M与C的表格式总结,谢谢他的那篇文章,我直接拉了过来。

Mutex 和 Critical Section 的异同 - 表格形式,一目了然

Posted on Tuesday, July 11, 2006 4:02 PM #C & C++

[align=left]Mutex和Critical Section都是主要用于限制多线程(Multithread)对全局或共享的变量、对象或内存空间的访问。下面是其主要的异同点(不同的地方用绿色表示)。[/align]
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,WaitForMultipleObjectsEx,MsgWaitForMultipleObjects,MsgWaitForMultipleObjectsEx等等)
不可
当拥有锁的线程死亡时
Mutex变成abandoned状态,其他的等待线程可以获得锁。
Critical Section的状态不可知(undefined),以后的动作就不能保证了。
自己会不会锁住自己
不会(对已获得的Mutex,重复调用WaitForSingleObject不会锁住自己。但最后你别忘了要调用同样次数的ReleaseMutex)
不会(对已获得的Critical Section,重复调用EnterCriticalSection不会锁住自己。但最后你别忘了要调用同样次数的LeaveCriticalSection)
[align=left] [/align]
[align=left]下面是一些补充:[/align]
[align=left]l 请先检查你的设计,把不必要的全局或共享对象改为局部对象。全局的东西越少,出问题的可能就越小。[/align]
[align=left]l 每次你使用EnterCriticalSection时,请不要忘了在函数的所有可能返回的地方都加上LeaveCriticalSection。对于Mutex也同样。若你把这个问题和Win32 structured exception或C++ exception一起考虑,你会发现问题并不是那么简单。自定义一个封装类可能是一种解决方案,以Critical Section为例的代码如下所示:[/align]
[align=left]class csholder[/align]
[align=left]{[/align]
[align=left] CRITICAL_SECTION *cs;[/align]
[align=left]public:[/align]
[align=left] csholder(CRITICAL_SECTION *c): cs(c)[/align]
[align=left] { EnterCriticalSection(cs); }[/align]
[align=left] ~csholder() { LeaveCriticalSection(cs); }[/align]
[align=left]};[/align]
[align=left] [/align]
[align=left]CRITICAL_SECTION some_cs;[/align]
[align=left]void foo()[/align]
[align=left]{[/align]
[align=left] // ...[/align]
[align=left] csholder hold_some(&some_cs);[/align]
[align=left] [/align]
[align=left] // ... CS protected code here[/align]
[align=left] [/align]
[align=left] // at return or if an exception happens[/align]
[align=left] // hold_some's destructor is automatically called[/align]
[align=left]}[/align]
[align=left]l 根据你的互斥范围需求的不同,把Mutex或Critical Section定义为类的成员变量,或者静态类变量。[/align]
[align=left]l 若你想限制访问的全局变量只有一个而且类型比较简单(比如是LONG或PVOID型),你也可以使用InterlockedXXX系列函数来保证一个线程写多个线程读。[/align]
[align=left] [/align]
[align=left] [/align]
[align=left]本文主要参照了Jeffrey Richter的《Programming Applications for Microsoft Windows, 4th Ed.》。[/align]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: