什么是虚假唤醒(spurious wakeup)?

什么是虚假唤醒(spurious wakeup)?如何处理?

java虚假唤醒spurious wakeup
1
311
已修改
小课
小课2022-06-13 16:54
1 个回答

在多线程开发中,经常会有一个线程等待另外一个线程的情况,常用的Object.wait()/Object.notify()Condition.await()/Condition.signal()

1public final static Object lockObj = new Object();
2
3//Thread A
4synchronized (lockObj) {
5    lockObj.wait(10000);
6}
7
8//Thread B
9synchronized (lockObj) {
10    lockObj.notify();
11}

一般情况下,线程A进入等待状态后,有以下几种情况会导致线程A唤醒继续执行。

  • 其它线程调用了notify或者notifyAll,使得线程A获取到了对象锁。
  • 线程A被中断(interrupt)了,抛出异常后继续执行。
  • 线程A等待的时间超过设定的时间。

以上是三种比较正常的情况,但是还有一种特殊情况,就是虚假唤醒(spurious wakeup),在Object.wait()Condition.await()方法的注释有中提到

A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup.

拿Object.wait()方法来说,也就是说即使没有其它线程调用notify,也有可能使等待中的线程被唤醒,当然这种情况比较少出现,但是还是需要预先做好处理。Object.wait()的注释中也已经给出了处理方案,就是在唤醒之后需要再次判断是否已经满足条件,如果满足则继续执行,否则继续等待直到正确唤醒。

synchronized (lockObj) {
    while (条件不满足) {
        lockObj.wait(timeout);
    }
    ...
}
1
已修改
小课
小课2022-06-13 17:08
你的回答

内容