【问题标题】:std::condition_variable wait_for infinitestd::condition_variable wait_for 无限
【发布时间】:2017-06-24 03:47:04
【问题描述】:

我正在尝试使用以下代码对条件变量进行无限等待(只是显示问题的示例):

std::condition_variable cond;
std::mutex mtx;
std::unique_lock<std::mutex> lock(mtx);
cond.wait_for(lock, std::chrono::steady_clock::duration::max());

但是等待立即退出。深入挖掘wait_for 的(MS)实现,我发现它实际上使用了wait_until 函数。但在此之前,它会通过调用chrono::system_clock::now() 来转换时间并添加持续时间。

当然这会导致整数溢出,因此新时间变为 wait_until 立即退出。 所有其他定时等待函数(例如std::timed_mutex 类中的try_lock_for)也是如此。

总结以上内容,我想问一下这是否是定时等待功能的实现中的一个错误,如果是,那么我在哪里可以写呢?

另外,由于wait_until 使用system_clock,如果等待期间有时间调整,实际等待时间应该会有所不同(因为system_clock 不是单调的)。因此不存在等待持续时间的信任。

【问题讨论】:

  • 您是否考虑过改用wait 函数?等待没有计时器。
  • 恕我直言,这是一个spurious wakeup
  • @megabyte1024 这不是虚假的,因为它很容易重现。等待函数的返回值也是“超时”,所以根本没有唤醒
  • @megabyte1024 如果您将等待时间设置为一些不太极端的值,例如 10 秒左右,则会发生等待
  • @ArtyomChirkov,这可能是实现中的一个问题。但重要的是要了解所有 std::condition_variable wait 方法可能会被虚假地解除阻塞。使用没有谓词作为参数的wait 函数的唯一正确方法是在循环内部的互斥锁和等待方法调用之间“包装”一个带有自己变量的循环。在这种情况下,“易于使用”的方法是 waitwait_until

标签: c++ c++11 synchronization wait condition-variable


【解决方案1】:

cppreference documentation 说:

请注意,rel_time 必须足够小,以免在添加到 std::chrono::steady_clock::now() 时溢出。

还有:

使用绑定到 timeout_time 的时钟,它不需要是单调时钟。如果时钟不连续调整,则无法保证此函数的行为,但现有实现将 timeout_time 从 Clock 转换为std::chrono::system_clock并委托给 POSIX pthread_cond_timedwait 以便等待对系统时钟进行调整,而不是对用户提供的时钟进行调整。在任何情况下,由于调度或资源争用延迟,该函数也可能等待比到达timeout_time 更长的时间。

即使正在使用的时钟是std::chrono::steady_clock 或其他单调时钟,系统时钟调整也可能导致虚假唤醒。

如果您想要无限超时,您可以这样做(未测试):

wait_until(lock, std::chrono::sys_time::max());

【讨论】:

    猜你喜欢
    • 2019-01-22
    • 2020-02-19
    • 2015-02-27
    • 2017-05-14
    • 1970-01-01
    • 2013-10-20
    • 2016-03-11
    • 2015-12-22
    • 2012-11-02
    相关资源
    最近更新 更多