什么是虚假唤醒(spurious wakeup)?如何处理?
在多线程开发中,经常会有一个线程等待另外一个线程的情况,常用的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唤醒继续执行。
以上是三种比较正常的情况,但是还有一种特殊情况,就是虚假唤醒(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);
}
...
}
内容