什么可以唤醒一个条件变量

时间:2014-01-28 16:56:16

标签: c++ multithreading winapi

我实现了一个简单的ThreadPool,它使用std::list<Tasks> mTasks作为任务列表。

所有线程使用以下代码等待条件变量:

EnterCriticalSection(&mCriticalSection);

while(mTasks.size() ==0)
    SleepConditionVariableCS(&mConditionVariable,&mCriticalSection, INFINITE);

直到有人在列表中添加内容然后其中一个被唤醒。

我用了一段时间来检查任务列表是不是空的,虽然被唤醒的唯一方法是向列表中添加一个新任务(因此它不能为空),我这样做的原因是因为在MSDN中写道:

  

条件变量受到虚假唤醒(那些不是   与明确的唤醒相关联和被盗的唤醒(另一个线程   设法在唤醒线程之前运行。因此,你应该重新检查   睡眠操作后的谓词(通常在while循环中)   回报。

但那些虚假的唤醒是什么,什么会唤醒我的变量?

2 个答案:

答案 0 :(得分:2)

在我在大学学习的时候,我对这个主题的理解是,从绩效的角度来看,实施100%安全的条件变量实在太贵了。

关于spurious wakeups的维基百科页面引自David R. Butenhof(Programming with POSIX Threads的作者)说:

  

这意味着当您等待条件变量时,等待可能会   (偶尔)没有专门广播的线程或   发出条件变量的信号。虚假的唤醒可能听起来很奇怪,   但在某些多处理器系统上,完全唤醒条件   可预测的可能会大大减慢所有条件变量   操作。引起虚假唤醒的竞争条件应该是   被认为是罕见的

检查while循环中的条件是一种很好的做法,可以避免这个问题。

如果有更多关于为什么会发生这种情况的细节,我很抱歉,但我无法提供这样的见解。

答案 1 :(得分:1)

我认为问题在于多处理器系统中多个处理器之间的同步问题。

为了使条件变量保持尽可能轻量级,实现使用某些线程原语,虽然线程安全,但是当实际只有一个时,会导致条件变量注册两个notify()样式调用。这是一种罕见的情况,而不是通过处理这种情况降低效率,设计人员将问题推送到用户代码中,如果它可能会影响您,您只需要担心它。