gal*_*tte 6 c++ multithreading std condition-variable c++11
在std :: condition_variable的文档中,使用谓词函数作为参数的wait()重载。该函数将一直等到谓词函数为true的第一次wake_up。
在文档中
据说这相当于:
while (!pred()) {
wait(lock);
}
Run Code Online (Sandbox Code Playgroud)
但是也:
在等待特定条件变为真时,可以使用此重载来忽略虚假唤醒。请注意,在进入此方法之前,必须先获取锁,在wait(lock)退出后也必须重新获取它,即锁可以用作pred()访问的保护。
我不确定这些是严格等同的(在这种情况下,我更喜欢普通的while循环,而在我的情况下,这种循环比带有lambda的重载更易于阅读),或者重载(可能取决于实现)更有效?
为了避免测试条件为假时唤醒,实现是否可以在唤醒等待线程之前评估通知线程中的谓词?这里需要c ++线程大师...
谢谢
从性能的角度来看,实现可以尝试使它比循环更好,但我怀疑这是可能的。它非常直接,您可以检查您的实现以了解它是如何完成的。这就是 gcc 4.9.2 在这里所做的:
template<typename _Predicate>
void
wait(unique_lock<mutex>& __lock, _Predicate __p)
{
while (!__p())
wait(__lock);
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它完全相同,我怀疑这里是否可以做其他事情。至于可读性,它比循环更具可读性。但是,您可能误解了这样做的原因。这个循环只是为了检查由条件保护的真实变量是否确实更改为您期望的值 - 因为它可能没有。剪下的通常代码如下所示:
cond_var.wait(lock, []() { return bool_var == true; })
Run Code Online (Sandbox Code Playgroud)
据我的理解,这两个(while
循环和wait + predicate
)在功能上是等效的。如果您使用while
循环,则应在第一次进入和评估循环条件之前获取锁定。每隔一段时间,您也会持有锁,就像在完成predicate()
后执行一样。wait()
重载在内部执行相同的操作:您必须在调用之前获取锁wait
,并且在 wait 完成后在predicate()
内部调用以检查我们是否应该继续等待(就像 while 循环所做的那样)。
也许您是对的,因为boolean
使用while
循环简单返回值的简单谓词更清晰。但如果predicate
变得更复杂怎么办?为其定义一个专用函数并在 while 循环条件中使用它,还是就地使用 lambda?如果谓词数量增加怎么办,您会为每个谓词定义函数吗?在我看来,在这种情况下使用 lambda 可以使代码更清晰,因为整个事物都保存在一个逻辑单元中。