今天我在Boost线程文档上看到了一个有趣的段落:
void wait(boost::unique_lock<boost::mutex>& lock)
..。
效果:原子调用lock.unlock()并阻塞当前线程。当调用this-> notified ()或this->notified()或伪造时,线程将解除阻塞。当线程被解除阻塞时(无论出于什么原因),在调用等待返回之前,通过调用lock.lock()重新获取锁。如果函数在异常情况下退出,则通过调用lock.lock()重新获取锁。
所以我感兴趣的是“伪造”这个词的意思。为什么线程会因为虚假的原因而被解除阻塞?如何才能解决这一问题?
发布于 2009-03-09 08:14:43
本文作者安东尼·威廉姆斯特别详细。
虚假的尾迹是无法预测的:从用户的角度来看,它们本质上是随机的。但是,当线程库无法可靠地确保等待的线程不会错过通知时,通常会发生这种情况。由于遗漏的通知会使条件变量失效,线程库会从等待中唤醒线程,而不是冒险。
他还指出,您不应该使用需要持续时间的timed_wait
重载,而且通常应该使用使用谓词的版本
这是初学者的错误,也是一个简单规则很容易克服的错误:在使用条件变量等待时,一定要在循环中检查谓词。更阴险的bug来自timed_wait()。
本文作者为Vladimir Prus也很有趣。
但是为什么我们需要while循环,我们不能写:
if (!something_happened)
c.wait(m);
我们不能。凶手的原因是“等待”可以在没有任何“通知”的情况下返回。这被称为虚假唤醒,并被POSIX明确允许。本质上,从“等待”返回仅表示共享数据可能已经更改,因此必须再次计算数据。 好吧,为什么这个还没修好?第一个原因是没有人想要解决这个问题。出于其他几个原因,在循环中将调用包装为“等待”是非常理想的。但这些原因需要解释,而虚假的唤醒是一个锤子,可以适用于任何一年级的学生,不可能失败。
发布于 2009-03-09 08:14:04
这篇博客文章给出了Linux的一个理由,即当信号被传递到进程时返回futex
系统调用。不幸的是,它并没有解释其他任何事情(而且确实是在要求更多的信息)。
维基百科虚假唤醒条目 (这似乎是一个posix的概念,顺便说一句,不限于提振)可能也会让你感兴趣。
https://stackoverflow.com/questions/625340
复制相似问题