【问题标题】:How often false signals are triggered in a condition variable?在条件变量中触发错误信号的频率如何?
【发布时间】:2020-02-18 07:49:33
【问题描述】:

我不明白为什么 std::condition_variable 比这段代码有更多的标准保证:

class condition_variable {
public:
  void notify_one() {}
  void notify_all() {}
  void wait(unique_lock<mutex> &lock) {
    lock.unlock();
    this_thread::sleep_for(15ms);
    lock.lock();
  }
  void wait(unique_lock<mutex> &lock,
            const function<bool()> &pred) {
    while (!pred()) wait(lock);
  }
};

【问题讨论】:

  • 关于错误信号触发器的问题 - 在某些系统上可能没有(以免调用程序终止或类似的东西),只有通知会重新唤醒线程。但在其他一些系统上它可能会更大。
  • 好吧,对于初学者来说,你是怎么碰巧选择了 15ms 的?我们希望为任何给定操作系统和硬件平台实现wait() 的人将针对特定操作系统/硬件组合以最佳方式执行此操作。事实上,wait() 被允许“虚假地”返回,这一事实为某些操作系统和硬件组合的实现者提供了使其工作方式的一些灵活性。

标签: c++ multithreading condition-variable


【解决方案1】:

std::condition_variable::wait() 的最简单实现只对应于忙等待

template<typename Predicate>
void wait(std::unique_lock<std::mutex>& lck, Predicate pred) {
   while (!pred()) {
      lck.unlock();
      lck.lock();
   }
}

因此,可能会发生虚假唤醒

您的实现在释放和获取互斥锁上的锁之间使线程休眠:

void wait(unique_lock<mutex> &lock) {
   lock.unlock();
   this_thread::sleep_for(15ms); // <--
   lock.lock();
}

不过,找到合适的睡眠时间可能很困难。它越低,越像忙等待,因此浪费的 CPU 周期越多。它越高,浪费的 CPU 周期越少,但响应能力越差。

您的实现中发生虚假唤醒的频率取决于睡眠期的选择。

【讨论】:

    【解决方案2】:

    条件变量旨在使用a semaphore,它允许在不使用 CPU 周期的情况下等待。您的实现会反复锁定和解锁互斥锁,如果没有睡眠,它将消耗 100% 的 CPU。

    随着睡眠,唤醒时有固定的延迟,这与信号量相比也是一个缺点。操作系统知道谁在等待每个条件变量,因此唤醒是有效的。

    在 Windows 上,std::condition_variable 会使用SleepConditionVariableCS 等待,并且通常使用操作系统条件变量 API。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-07
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 1970-01-01
      • 2015-06-10
      • 2011-07-18
      • 2011-10-19
      相关资源
      最近更新 更多