首页 文章

std :: condition_variable ::等待谓词

提问于
浏览
4

在std :: condition_variable的文档中,有一个wait()重载作为参数作为谓词函数 . 该函数将一直等到谓词函数为真的第一个wake_up .

documentation

据说这相当于:

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

但是也:

此异常可用于在等待特定条件变为真时忽略虚假唤醒 . 注意,在进入此方法之前必须获取锁定,在等待(锁定)退出之后它也被重新获取,即锁定可以用作对pred()访问的保护 .

我不太明白,这些是否严格等效(在这种情况下,我更喜欢简单的while循环,这比我在案例中使用lambda的重载更容易阅读),还是过载(可能依赖于实现)更有效?

在唤醒等待线程之前,实现是否可以评估通知线程中的谓词,以避免在测试条件为假时唤醒?这里需要c线程大师......

谢谢

2 回答

  • 0

    从性能角度来看,实现可以尝试使其优于循环,但我怀疑它是否可行 . 这是非常严格的,你可以检查你的实现,看看它是如何完成的 . 这是gcc 4.9.2在这里做的:

    template<typename _Predicate>
      void
      wait(unique_lock<mutex>& __lock, _Predicate __p)
      {
          while (!__p())
            wait(__lock);
      }
    

    正如您所看到的,它完全相同,我怀疑其他事情可以在这里完成 . 至于可读性,它比循环更易读 . 但是,你可能误解了原因 . 这个循环应该只是检查由条件保护的实变量是否确实变为你期望的值 - 因为它可能没有 . 通常的代码剪断看起来像这样:

    cond_var.wait(lock, []() { return bool_var == true; })
    
  • 2

    据我所知,这两个( while 循环和 wait + predicate )功能相同 . 如果您使用 while 循环,则应在首次输入和评估循环条件之前获取锁定 . 在 wait() 完成后,每隔一次你也会按住 predicate() 执行 .

    内部的重载执行相同的操作:您必须在调用 wait 之前获取锁定,并且在等待完成后,内部调用 predicate() 以检查是否应该继续等待(就像while循环一样) .

    也许你是对的,对于使用 while 循环简单地返回 boolean 值的简单谓词更清楚 . 但是如果 predicate 变得更复杂呢?为它定义一个专用函数并在while循环条件下使用它,或者使用lambda?如果谓词数量增加,您会为每个谓词定义函数吗?在我看来,在这种情况下使用lambdas可以使代码更清晰,因为整个事物在一个逻辑单元中保存在一起 .

相关问题