我在提升线程文档 http://www.boost.org/doc/libs/1_38_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref today:
void wait(boost::unique_lock<boost::mutex>& lock)
...
效果:原子调用lock.unlock()
并阻塞当前线程。这
线程将在收到通知时解除阻塞
调用 this->notify_one() 或
this->notify_all(),或者虚假地。
当线程被解除阻塞时(对于
无论什么原因),锁是
通过调用lock.lock()重新获取
在 wait 调用返回之前。这
锁也可以通过调用重新获取
lock.lock() 如果函数退出
一个例外。
所以我感兴趣的是“虚假”这个词的含义。为什么线程会因虚假原因而被解除阻塞?可以采取什么措施来解决这个问题?
本文作者:安东尼·威廉姆斯 http://www.justsoftwaresolutions.co.uk/threading/condition-variable-spurious-wakes.html写得特别详细。
无法预测虚假唤醒:
它们本质上是随机的
用户的观点。然而,他们
通常发生在线程库
不能可靠地确保等待
线程不会错过任何通知。
由于错过通知会
使条件变量无用,
线程库唤醒线程
从它的等待而不是采取
风险。
他还指出你不应该使用timed_wait
需要一段时间的重载,通常应该使用带有谓词的版本
这是初学者的错误,其中之一
这很容易用一个简单的方法克服
规则:总是检查你的谓词
等待条件时循环
多变的。更阴险的bug来了
来自 timed_wait()。
本文作者:弗拉基米尔·普鲁斯 http://vladimir_prus.blogspot.com/2005/07/spurious-wakeups.html也很有趣。
但为什么我们需要 while 循环,
我们不能写:
if (!something_happened)
c.wait(m);
我们不能。致命的原因是“等待”可以
返回没有任何“通知”调用。
这就是所谓的虚假唤醒
POSIX 明确允许。
本质上,仅从“等待”返回
表明共享数据可能
已更改,因此数据必须
再次评价。
好吧,那为什么这个问题还没有解决呢?
第一个原因是没人愿意
要解决这个问题。将呼叫包装为“等待”
一个循环对于几个人来说是非常需要的
其他原因。但那些原因
需要解释,虽然是虚假的
唤醒是一个可以应用的锤子
任何一年级学生没有
失败。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)