作者:Aetherus
链接:https://www.zhihu.com/question/439926072/answer/1687513977
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
因为Java有个叫“spurious wakeup”的神奇现象,即线程在不该醒过来的时候醒过来。
Oracle官方API文档对java.lang.Object#wait(long, int)
方法的描述里有这么一段:
A thread can wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied.
大意:
一个线程有可能会在未被通知、打断、或超时的情况下醒来,这就是所谓的“spurious wakeup”。尽管实际上这种情况很少发生,应用程序仍然必须对此有所防范,手段是检查正常的导致线程被唤醒的条件是否满足,如果不满足就继续等待。
打个比方,你和你的哥们儿在火车站候车大厅等车。由于离火车到站还有段时间,你决定去睡一觉。以下几种情况会让你醒过来:
- 睡到自然醒(timed out)
- 车站广播“开往XX的列车即将到站”(notified)
- 哥们儿把你拖起来吃鸡(interrupted)
- 做噩梦(spurious wakeup)
如果是做噩梦醒来,你得看看火车是不是快到了,如果没到则继续睡。如果你运气很背,可能会做好几个噩梦,所以要while循环。