【问题标题】:Must the std::condition_variable predicate be checked before waiting?必须在等待之前检查 std::condition_variable 谓词吗?
【发布时间】:2020-08-05 12:34:35
【问题描述】:

从文档语言中我不清楚是否必须在等待之前检查 std::condition_variable 的谓词。

cppreference,有这样的说法:

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 

在实践中,似乎不需要检查。如果没有,我只是担心未定义的行为。

我关心的情况是消费者在生产者之后上线的情况(即条件变量在另一个线程开始等待之前已经被一个线程通知):

#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;
}

在上面的示例中,生产者启动并通知条件变量。消费者在那之后开始,并在检查条件变量之前休眠几秒钟。这实际上确保了消费者在生产者通知条件变量后开始等待。

尽管如此,代码在我的计算机上完成并且不会无限期挂起。事实上,由于它完成的速度有多快,我认为这不是由于虚假唤醒,但我不确定如何检查。

【问题讨论】:

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


【解决方案1】:

没有。

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

The cited cppreference.com article 在这方面可以说是误导(和/或错误),尽管the article for wait 在其基于代码的示例中很重要,这与the definition given in the standard 相同:

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

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

这可能是因为wait() 的重载不会采用pred,并且一般不需要条件变量了解您正在测试的条件:很有可能使用它来检查一些“外部”条件。但是,现在,我们通常只是将一个 lambda 推入 pred 并完成它,所以……

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-22
    • 1970-01-01
    • 2014-03-12
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 2023-03-13
    相关资源
    最近更新 更多