简体   繁体   English

C++中的条件变量wait_for

[英]condition_variable wait_for in C++

I am working with condition_variable on Visual studio 2019. The condition_variable.wait_for() function returns std::cv_status::no_timeout without any notification.我有工作condition_variable上的Visual 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;
}

I think the code will never exit and keep printing * , but it exits after printing some * .我认为代码永远不会退出并继续打印* ,但它在打印一些*后退出。

Here is the output:这是输出:

********************************************************************thread exits
program exits

Why does this happen?为什么会发生这种情况? Is it the so-called "spurious wakeups"?难道就是所谓的“虚假唤醒”?

Yes, it's a "spurious wakeup".是的,这是一个“虚假唤醒”。 This is explained on cppreference.com's reference page for wait_for :这在cppreference.com 的wait_for参考页面上有解释:

It may also be unblocked spuriously.它也可能被虚假地解除阻塞。 When unblocked, regardless of the reason, lock is reacquired and wait_for() exits.解除阻塞时,无论何种原因,都会重新获取锁并退出 wait_for()。

Translation: there are gremlins in your computer.翻译:您的计算机中有小鬼。 They get grumpy, occasionally.他们偶尔会脾气暴躁。 And if they do get grumpy, wait_for returns before the requested timeout expires.如果他们确实变得脾气暴躁, wait_for在请求的超时到期之前返回。 And when that happens:当这种情况发生时:

Return value返回值

  1. std::cv_status::timeout if the relative timeout specified by rel_time expired, std::cv_status::no_timeout otherwise.如果 rel_time 指定的相对超时过期,则为 std::cv_status::timeout,否则为 std::cv_status::no_timeout。

And that seems to be exactly what you're seeing.这似乎正是你所看到的。 The C++ standard permits a C++ implementation to return from wait_for prematurely, for arbitrary reasons, and unless you do return from wait_for when the timeout expires, no_timeout is what you get. C++ 标准允许 C++ 实现出于任意原因过早地从wait_for返回,除非您在超时到期时确实wait_for返回,否则您得到no_timeout

You might be wondering why wait_for (and several other similar functions) may decide to throw up their hands and return "spuriously".您可能想知道为什么wait_for (以及其他几个类似的函数)可能会决定举手并“虚假地”返回。 But that would be a different question...但那将是一个不同的问题......

As already explained, it is waking up due spurious wakeup .正如已经解释过的,它是由于spurious wakeupspurious wakeup Such thing make the function wait_for completely useless.这样的事情使函数wait_for完全无用。 The solution is to use the wait_until saving the current time before entering the wait loop:解决方法是在进入等待循环之前使用wait_until保存当前时间:

int count = 1;
std::mutex mutex;
std::condition_variable condition_variable;

void wait() {
    std::unique_lock<std::mutex> lock(mutex);
    count--;

    int timeout = 1000; // 1 second
    std::chrono::time_point<std::chrono::system_clock> timenow = 
        std::chrono::system_clock::now();

    while(count < 0) {
        std::cv_status status = condition_variable.wait_until(
            lock, 
            timenow + std::chrono::duration<double,std::ratio<1,1000>>(timeout));

        if ( std::cv_status::timeout == status) {
            count++;
            break;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM