我想知道为什么线程会自动从java中的wait()中唤醒 这是一个设计决定吗?这是妥协吗?
编辑:(来自Java Concurrency in Practice,p.300)
wait
甚至被允许返回 “虚假地” - 不回应任何 线程调用通知。
此外,作者还说:
这就像一个松散的烤面包机 使钟响的连接 当吐司准备好的时候 有时候还没有准备好。
这就是为什么你总是需要像
这样的代码synchronized(this){
while(!condition)
wait();
}
}
永远不会
synchronized(this){
if(!condition){
wait();
}
}
即使条件仅从中转换
false
到true
。
答案 0 :(得分:24)
这些自发的唤醒也被称为“虚假的唤醒”。在Java规范中,对于jvm实现,虚假的唤醒是允许的(尽管不鼓励)。
允许它们的原因是因为许多实现可能基于具有此行为的pthread(POSIX线程)。为什么呢?
根据David R. Butenhof的说法 用POSIX Threads编程ISBN 0-201-63392-2:“这意味着何时 你等一个条件变量, 等等可能(偶尔)返回时没有 线程专门广播或 发出条件变量的信号。 虚假的唤醒可能听起来很奇怪, 但在一些多处理器系统上, 让条件完全唤醒 可预测的可能会大大放缓 所有条件变量操作。该 引起虚假的种族条件 唤醒应该被认为是罕见的。“
答案 1 :(得分:10)
由于Java语言规范没有声明为什么 JVM实现可能想要这样做(它只能指定它可以,in this section),因此很难回答这个问题。我找到了a pretty interesting history of spurious wake-ups on Wikipedia。
关于POSIX线程的实际文章,但我认为假设Java中的线程受POSIX线程行为的影响有点太过分了:
虚假唤醒可能听起来很奇怪,但在某些多处理器系统上,使条件唤醒完全可预测可能会大大减慢所有条件变量操作。引起虚假唤醒的竞争条件应该被认为是罕见的。
这句话来自David R. Butenhof,然后接着说:
虽然确实有一些工作组成员认为理论上可以想象可能存在这样的实现,但事实并非如此。 (并且它们永远无法证明它。)POSIX线程是实用的硬实时程序员和主要是学术研究人员之间的紧张关系的结果。虚假的唤醒是学术计算机科学家集团的机制,以确保每个人都必须编写检查和验证谓词的干净代码!
“但是(或许)很大程度上是虚假的(或至少是古怪的哲学)”效率“论证在实时人员中得到了更好的改善,而真正的理由通常被归为理论中的第二位。
“我多次想过你如何构建一个真正实用的实际实现虚假的唤醒。我从来没有设法构建一个例子。但并不意味着没有一个例子。这是一个很好的故事。