【问题标题】:What can wake up a conditional variable什么可以唤醒条件变量
【发布时间】:2014-01-28 16:56:16
【问题描述】:

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

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

EnterCriticalSection(&mCriticalSection);

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

直到有人在列表中添加了一些东西,然后其中一个被唤醒。

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

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

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

【问题讨论】:

  • 阻塞队列逻辑也应该在这里工作。
  • 我添加了winapi 标签,但是其他操作系统也会发生虚假唤醒。
  • @Nawaz 我不明白你的评论
  • @OopsUser:搜索“阻塞队列”或“并发阻塞队列”。
  • @OopsUser:见put() and take() here的实现。您需要做的就是模仿类似的行为。

标签: c++ multithreading winapi


【解决方案1】:

当我在大学学习这个主题时,我对这个主题的理解是,从性能角度来看,实施 100% 安全条件变量的成本太高了。

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

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

检查while 循环中的条件是一个很好的做法,肯定会避免这个问题。

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-24
      • 1970-01-01
      • 2017-11-09
      • 2011-08-01
      相关资源
      最近更新 更多