【发布时间】:2010-11-15 23:15:58
【问题描述】:
事件对象和条件变量有什么区别? 我在 WIN32 API 的上下文中询问。
【问题讨论】:
标签: c++ multithreading winapi synchronization
事件对象和条件变量有什么区别? 我在 WIN32 API 的上下文中询问。
【问题讨论】:
标签: c++ multithreading winapi synchronization
事件对象是内核级对象。它们可以跨进程边界共享,并且在所有 Windows 操作系统版本上都受支持。如果需要,它们可以用作共享资源的独立锁。由于它们是内核对象,因此操作系统对一次可以分配的可用事件的数量有限制。
条件变量是用户级对象。它们不能跨进程边界共享,并且仅在 Vista/2008 和更高版本上受支持。它们不充当自己的锁,但需要单独的锁与它们关联,例如临界区。由于它们是用户对象,可用变量的数量受可用内存的限制。当条件变量进入睡眠状态时,它会自动释放指定的锁对象,以便另一个线程可以获取它。当条件变量被唤醒时,它会自动重新获取指定的锁对象。
就功能而言,将条件变量视为两个对象协同工作的逻辑组合——keyed event 和锁定对象。当条件变量进入睡眠状态时,它会重置事件,释放锁,等待事件发出信号,然后重新获取锁。例如,如果您使用临界区作为锁定对象,SleepConditionalVariableCS() 类似于对ResetEvent()、LeaveCriticalSection()、WaitForSingleObject() 和EnterCriticalSection() 的一系列调用。而如果您使用 SRWL 作为锁,SleepConditionVariableSRW() 类似于对ResetEvent()、ReleaseSRWLock...()、WaitForSingleObject() 和AcquireSRWLock...() 的一系列调用。
【讨论】:
SleepConditionVariableCS() 的情况下,它更有可能使用SleepEx(),并被超时或来自WakeConditionVariable() 的APC 唤醒。我更新了答案以反映这一点。
WinNT.h 中RTL_CRITICAL_SECTION 的定义),但我刚刚意识到我误读了您的答案——您说的是CV,而不是CS。事实上,一个关键事件是最有可能的。 CS 肯定需要一个事件或信号量或其他东西,以便它可以在需要时进入内核等待,但 CV 似乎不需要。
最显着的区别是Event对象是内核对象,只要进程/线程试图获取时它还活着,就可以跨进程共享,相反,Condition变量是轻量级的用户态对象(仅与指针大小相同,使用后没有任何额外的释放)并且具有更好的性能。
通常情况下,条件变量通常与锁一起使用,因为我们需要保持数据正确同步。在考虑条件变量时,我们将其视为自 Vista 以来改进的键控事件。
Joe duffy 有一篇博文 http://joeduffyblog.com/2006/11/28/windows-keyed-events-critical-sections-and-new-vista-synchronization-features/ 解释了更详细的信息。
【讨论】:
它们非常相似,但事件对象跨流程边界工作,而条件变量则不然。来自MSDN documentation on condition variables:
条件变量是用户模式的 无法共享的对象 进程。
来自MSDN documentation on event objects:
其他进程中的线程可以打开一个 处理现有事件对象 在调用 打开事件函数。
【讨论】: