等待前是否必须检查std::condition_variable谓词



根据文档语言,我不清楚在等待之前是否必须检查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("%sn", "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("%sn", "Consumer finished");
}
});
for (auto& thread : threads) {
if (thread.joinable()) {
thread.join();
}
}
return 0;
}

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

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

如果向wait提供谓词,则在调用函数之前不需要自己检查它。

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

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

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

这可能是因为wait()过载,不采用pred,而通常不要求条件变量了解您正在测试的条件:很可能使用它来检查某些"外部"条件。但是,现在,我们通常只是把lambda推到pred中并完成它,所以…

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

最新更新