std :: condition_variable ::等待谓词

时间:2015-11-13 12:16:09

标签: c++ multithreading c++11 std condition-variable

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

documentation

据说这相当于:

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

但是:

  

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

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

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

由于

2 个答案:

答案 0 :(得分:2)

从性能角度来看,实现可以尝试使其优于循环,但我怀疑它是否可行。这是非常严格的,你可以检查你的实现,看看它是如何完成的。这就是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; })

答案 1 :(得分:0)

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

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

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