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

Enn*_*oji 19 java concurrency multithreading

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

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

wait 甚至允许"虚假地"返回 - 不响应任何调用通知的线程.

作者进一步指出:

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

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

synchronized(this){
    while(!condition)
        wait();
    }
}
Run Code Online (Sandbox Code Playgroud)

永不

synchronized(this){
    if(!condition){
        wait();
    }
}
Run Code Online (Sandbox Code Playgroud)

即使条件仅从转换 falsetrue.

bit*_*itc 24

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

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

维基百科:

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


mat*_*t b 10

很难确切回答这个问题,因为Java语言规范没有说明为什么一个JVM实现可能要做到这一点(它仅规定是可以的,在本节),但我发现一个非常有趣的虚假唤醒,历史上维基百科.

关于POSIX线程的实际文章,但我认为假设Java中的线程受POSIX线程行为的影响有点太过分了:

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

这句话来自David R. Butenhof,然后他继续说:

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

"但(或许)很大程度上虚假(或至少是古怪的哲学)"效率"论证在实时人员中得到了更好的改善,而真正的理由通常被归为理论中的第二位.

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