【发布时间】:2016-03-02 19:03:40
【问题描述】:
我期待下例中的第二个线程挂起,因为它等待一个没有相应通知的对象。相反,它通过了 println,可能是由于虚假唤醒。
public class Spurious {
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
System.out.println("Hey!");
}
};
Thread t2 = new Thread() {
public void run()
{
try {
synchronized (t1) {
t1.wait();
}
} catch (InterruptedException e) {
return;
}
System.out.println("Done.");
}
};
t1.start();
t2.start();
}
}
输出:
Hey!
Done.
另一方面,如果删除“嘿!” println 从第一个线程,第二个线程确实会挂起。这在 MacOS 和 Linux 上都会发生。
知道为什么吗?
【问题讨论】:
-
只是一个猜测,但线程的死亡可能会导致任何服务员的虚假唤醒。如果没有
println(),t1 可能在 t2 开始等待之前就已经死了,并且错过了那个虚假的唤醒。 -
阅读 Object.wait() 和 Thread.join() 的 javadoc。您不应该对 Thread 类型的对象调用 wait。它在停止时通知,以唤醒加入它的其他线程。
-
@JBNizet 似乎是对的。虽然我无法在 Javadoc 中找到它,但如果您使用像
final Object lock = new Object()和t2这样的锁等待它(而不是等待t1),那么它总是挂起。 -
听起来我猜对了。
标签: java multithreading wait notify spurious-wakeup