180*_*ION 10 multithreading boost wait conditional-statements
我今天在Boost线程文档中遇到了这个有趣的段落:
void wait(boost::unique_lock<boost::mutex>& lock)
Run Code Online (Sandbox Code Playgroud)
...
效果:原子调用lock.unlock()并阻止当前线程.当通过调用this-> notify_one()或this-> notify_all()或虚假地通知时,线程将解除阻塞.当线程被解除阻塞(无论出于何种原因)时,通过在等待调用返回之前调用lock.lock()来重新获取锁.如果函数以异常退出,则还可以通过调用lock.lock()来重新获取锁.
所以我感兴趣的是"虚假地"这个词的含义.为什么线程会因为虚假原因而被解除阻塞?可以做些什么来解决这个问题?
180*_*ION 11
无法预测虚假的醒来:从用户的角度来看,它们基本上是随机的.但是,它们通常在线程库无法可靠地确保等待线程不会错过通知时发生.由于错过的通知会使条件变量无效,因此线程库会从等待中唤醒线程而不是冒险.
他还指出,您不应该使用timed_wait持续时间的重载,并且通常应该使用带谓词的版本
这是初学者的错误,并且可以通过一个简单的规则轻松克服:在等待条件变量时,总是在循环中检查谓词.更阴险的bug来自timed_wait().
弗拉基米尔普鲁斯的这篇文章也很有趣.
但是为什么我们需要while循环,我们不能写:
if (!something_happened)
c.wait(m);
Run Code Online (Sandbox Code Playgroud)
我们做不到.而杀手的原因是"等待"可以在没有任何"通知"电话的情况下返回.这称为虚假唤醒,POSIX明确允许.实质上,从"等待"返回仅表示共享数据可能已更改,因此必须再次评估数据.
好的,为什么这还没有修好呢?第一个原因是没有人想要解决它.由于其他几个原因,非常需要在循环中包含对"等待"的调用.但是这些原因需要解释,而虚假的唤醒是一把锤子,可以毫无疑问地应用于任何一年级学生.