C++中的条件变量wait_for

lfy*_*ybt 10 c++ condition-variable unique-lock

我正在使用condition_variableVisual Studio 2019。该condition_variable.wait_for()函数在std::cv_status::no_timeout没有任何通知的情况下返回。

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

std::condition_variable cv;
std::mutex mtx;
bool called = false;

void printThread()
{
    std::unique_lock<std::mutex> lck(mtx);
    while (std::cv_status::timeout == cv.wait_for(lck, std::chrono::seconds(1)))
    {
        std::cout << "*";
    }
    std::cout << "thread exits" << std::endl;
}

int main()
{
    std::thread th(printThread);
    th.join();
    std::cout << "program exits" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我认为代码永远不会退出并继续打印*,但在打印一些*.

这是输出:

********************************************************************thread exits
program exits
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况?难道就是所谓的“虚假唤醒”?

Sam*_*hik 11

是的,这是一个“虚假唤醒”。这在cppreference.com 的参考页面wait_for上有解释:

它也可能被虚假地解除阻塞。解除阻塞时,无论何种原因,都会重新获取锁并退出 wait_for()。

翻译:您的计算机中有小鬼。他们偶尔会脾气暴躁。如果他们确实变得脾气暴躁,则wait_for在请求的超时到期之前返回。当这种情况发生时:

返回值

  1. 如果 rel_time 指定的相对超时过期,则为 std::cv_status::timeout,否则为 std::cv_status::no_timeout。

这似乎正是你所看到的。C++ 标准允许 C++ 实现wait_for出于任意原因过早地返回,除非您在超时到期时确实返回,否则就是您得到的。wait_forno_timeout

您可能想知道为什么wait_for(以及其他几个类似的函数)可能会决定举手并“虚假地”返回。但那将是一个不同的问题......

  • @JHBonarius他的代码似乎假设条件变量有两种状态,有信号和无信号,如果条件变量处于有信号状态,它就会停止循环。但条件变量是无状态的——它们没有任何状态。这不是计时器溢出或其他什么。为了让这样的代码工作,程序员必须实现某种跟踪状态的方法,而这段代码却没有。所以它的行为是未定义的。 (2认同)