首页 > 解决方案 > Must the std::condition_variable predicate be checked before waiting?

问题描述

It is not clear to me from the documentation language whether one must check the predicate of a std::condition_variable before waiting.

On cppreference, there is the statement:

Any thread that intends to wait on std::condition_variable has to
    1. ...
    2. check the condition, in case it was already updated and notified 

In practice, it seems that one does not need to check. I am simply worried about undefined behavior if one does not.

The situation that I am concerned about is the one where a consumer comes online after a producer (that is, the condition variable has been notified by one thread before the other thread starts waiting for it):

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>

int main() {
  std::condition_variable condition_var;
  std::mutex mutex;
  std::vector<std::thread> threads;
  bool flag = false;

  // Producer
  threads.emplace_back([&]() {
    {
      std::lock_guard<std::mutex> lock(mutex);
      flag = true;
      printf("%s\n", "flag = true");
    }
    condition_var.notify_all();
  });

  // Consumer
  threads.emplace_back([&]() {
    std::this_thread::sleep_for(std::chrono::seconds(3));
    {
      std::unique_lock<std::mutex> lock(mutex);
      condition_var.wait(lock, [&]() { return flag; });
      printf("%s\n", "Consumer finished");
    }
  });

  for (auto& thread : threads) {
    if (thread.joinable()) {
      thread.join();
    }
  }
  return 0;
}

In the above example, a producer starts up and notifies a condition variable. The consumer starts after that, and is put to sleep for a few seconds before checking the condition variable. This practically ensures that the consumer starts waiting after the producer has notified the condition variable.

Despite this, the code finishes on my computer and does not hang indefinitely. In fact, due to how quickly it finishes, I presume that this is not due to spurious wakeup, but I am not sure how I would check that.

标签: c++multithreadingc++11c++14mutex

解决方案


不。

如果为 提供谓词wait,则无需在调用函数之前自行检查。

引用的 cppreference.com 文章在这方面可以说是误导(和/或错误),尽管文章wait在其基于代码的示例中是关于金钱的,这与标准中给出的定义相同:

while (!pred())
   wait(lock);

似乎该页面上的第二组要点是从更高级别的角度来解决问题的,没有考虑到wait()调用本身确实会为您执行检查pred()(如果您提供了一个)。

这可能是因为有一个不需要a的重载wait(),并且通常不需要条件变量知道您正在测试的条件:很有可能使用它来检查一些“外部”条件. 但是,如今,我们通常只是将 lambda 推入并完成它,所以……predpred

几周前我遇到了这种不一致(这里之前的讨论),但还没有为这篇文章想出更好的措辞。


推荐阅读