为什么线程会自动从wait()中唤醒?

我想知道为什么线程会自动从java中的wait()中唤醒。
这是一个设计决定吗? 这是妥协吗?

编辑:(来自Java Concurrency in Practice,p.300)

wait甚至被允许返回“虚假” – 不响应任何调用通知的线程。

作者进一步指出:

这就像一个连接器松动的烤面包机,当烤面包准备好时,铃铛会关闭,有时候还没有准备好。

这就是为什么你总是需要像

 synchronized(this){ while(!condition) wait(); } } 

永不

 synchronized(this){ if(!condition){ wait(); } } 

即使条件仅从false转换为true

这些自发的唤醒也被称为“虚假的唤醒”。 在Java规范中,jvm实现允许 (尽管不鼓励)虚假唤醒。

它们被允许的原因是因为许多实现可能基于具有此行为的pthreads(POSIX线程)。 为什么?

维基百科:

根据David R. Butenhof的POSIX Threads编程ISBN 0-201-63392-2:“这意味着当你等待条件变量时,等待可能(偶尔)在没有线程专门广播或发信号通知该条件变量时返回。唤醒可能听起来很奇怪,但在某些多处理器系统上,使条件唤醒完全可预测可能会大大减慢所有条件变量操作。导致虚假唤醒的竞争条件应该被认为是罕见的。

由于Java语言规范没有说明为什么 JVM实现可能想要这样做(它只能指明它可以在本节中 ),但很难肯定地回答这个问题,但我发现了一个非常有趣的虚假唤醒历史。维基百科 。

关于POSIX线程的实际文章,但是我认为Java中的线程在某种程度上受POSIX线程行为的影响并不是太过分了:

虚假唤醒可能听起来很奇怪,但在某些多处理器系统上,使条件唤醒完全可预测可能会大大减慢所有条件变量操作。 引起虚假唤醒的竞争条件应该被认为是罕见的。

这句话来自David R. Butenhof,然后接着说:

虽然确实有一些工作组成员认为理论上可以想象可能存在这样的实现,但事实并非如此。 (而且他们永远无法certificate这一点。)POSIX线程是实用的硬实时程序员和主要是学术研究人员之间的紧张关系的结果。 虚假的唤醒是学术计算机科学家集团的机制,以确保每个人都必须编写检查和validation谓词的干净代码!

“但(或许)很大程度上虚伪(或至少是古怪的哲学)”效率“论证与实时人员的关系更好,而真正的理由通常被归为理论中的第二位。

“我多次想过如何构建一个真正具有虚假唤醒的正确实用的实现。我从来没有设法构建一个例子。但并不意味着没有一个例子。好故事。