【问题标题】:C++ condition variable with no time out没有超时的 C++ 条件变量
【发布时间】:2020-06-02 07:18:09
【问题描述】:

最近,我遇到了一个与 C++ 中的条件变量有关的问题。代码如下:

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

std::condition_variable cv;
std::mutex mutex;

int main(){

std::unique_lock<std::mutex> uniqueLock(mutex);

while (true)
{

    if(cv.wait_for(uniqueLock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout)
    {
      std::cout << "has image" << std::endl;

    }
    else
    {
        std::cout<< "time out " << std::endl;
    }

}

return 0;
}

这段代码的目标是:每次在另一个线程(cv.notify())中通知条件变量时,在控制台中显示“有图像”,如果超过1000毫秒不能通知,它显示“超时”。

所以上面代码的理论输出是(因为没有通知条件变量):

time out
time out
time out
time out

但是当我在Vs2015中执行这段代码时,发现输出很奇怪:

has image
time out
has image
time out
time out
time out
has image
has image
time out
time out
time out
time out
time out
has image
has image

我想知道为什么我有这个输出以及如何实现我的目标

谢谢!

【问题讨论】:

  • 无法重现with gcc,但即使是MSVC 19 似乎也能重现produce the same outcome。大约一年前报告并修复了一个错误,请参阅here
  • 非常感谢 Daniel Langr,我想知道如果不下载链接中的发布版本,是否可以实现与我以另一种方式描述的相同的目标?

标签: c++ timeout condition-variable


【解决方案1】:

我不知道您的错误的原因是什么(但 cmets 中有一些似是而非的解释)。但是,解决问题的一种方法是使用 wait_for 的另一个重载,其中包含一个谓词。

它可能看起来像这样(hasImage 在这里只是一个布尔值,将其替换为对您的需求有意义的东西 - !imageStorage.empty() 或类似的):

while (true)
{

    if (cv.wait_for(uniqueLock, std::chrono::milliseconds(1000), []() {return hasImage;}))
    {
        std::cout << "has image" << std::endl;
        hasImage = false;
    }
    else
    {
        std::cout << "time out " << std::endl;
    }

}

相关的一点是谓词检查是否确实有新图像,如果没有,则应继续等待。

此方法的一个限制是,如果谓词返回 false(无图像),那么您不知道条件变量是否由于虚假唤醒、超时而被唤醒,或者实际上是否有图像但另一个线程刚刚在这个人醒来之前把它拿走了。但是,如果这是您的设计可以处理的问题,那么这种变化非常有效。

【讨论】:

  • 您好 Frodyne,非常感谢。我想知道 if (cv.wait_for(uniqueLock, std::chrono::milliseconds(1000), []() {return hasImage;})) 只有在 hasImage = true 时才能返回值,所以函数/线程谁通知条件变量(cv.notify_one())每次通知条件变量时需要设置hasImage = true。但是想象一下,如果这个线程/函数停止接收图像,从而停止通知条件变量,那么 hasImage 将不再设置为 true。在这种情况下,主函数将始终在 if 情况下阻塞。你对此有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 2022-11-15
  • 2017-02-27
  • 2021-12-28
  • 2010-12-31
  • 1970-01-01
  • 2011-11-26
  • 2017-09-13
  • 1970-01-01
相关资源
最近更新 更多