拜托,有人可以解释一下为什么这段代码是僵局。它似乎应该正常工作。请详细解释。感谢。
public class H extends Thread {
String info = "";
public H (String info) {
this.info = info;
}
public synchronized void run() {
try {
while (true) {
System.out.println(info);
notify();
wait();
}
} catch (Exception e) {}
}
public static void main(String[] args) {
new H("0").start();
new H("1").start();
}
}
答案 0 :(得分:5)
每个线程在this
上同步(通过方法上的synchronized
关键字),这对于两个线程对象中的每一个都是不同的。他们每个人都会调用notify
和wait
,但由于this
不同,他们不会互动。因此,在第一次迭代中,它们都会调用wait
并永久阻止,因为没有人可以将它们唤醒。
以下是我为使代码按预期工作所做的一些更改。注意允许线程进行通信的共享静态字段:
public class Test extends Thread {
String info = "";
static final Object signal = new Object();
static volatile String current = null;
public Test (String info) {
this.info = info;
}
public void run() {
try {
synchronized(signal) {
while (true) {
while(current.equals(info))
signal.wait();
System.out.println(info);
current = info;
signal.notify();
}
}
} catch (Exception e) {}
}
public static void main(String[] args) {
Test.current = "0";
new Test("0").start();
new Test("1").start();
}
}
我想对您的原始代码做一些其他说明:
Runnable
而不是扩展Thread
。它为您提供了更多的灵活性。答案 1 :(得分:3)
notify
和wait
在不同的Thread
对象上调用,因此当一个线程到达wait
时,另一个线程将不会通知它,而是,每个线程都会通知自己。
流程非常多(可能存在交错):
最终状态 - 两个线程都在等待,没有人通知它们。
答案 2 :(得分:1)
notify()仅唤醒当前正在等待该对象的线程。当你调用notify()时,在任何一种情况下都没有线程在等待。然后,当你调用wait时,你永远不会有任何通知()的代码。基本上,您无法从同一个线程通知线程,因为它必须等待。在等待一段时间之后尝试通过主线程通知它们,看看会发生什么。
public class H extends Thread {
String info = "";
public H (String info) {
this.info = info;
}
public synchronized void run() {
try {
while (true) {
System.out.println(info);
wait();
}
} catch (Exception e) {}
}
public static void main(String[] args) throws Exception {
H a = new H("0").start();
H b = new H("1").start();
Thread.sleep(1000);
a.notify();
b.notify();
}
}
请注意,两个线程都没有通知对方。等待一个对象只等待它,而不是完全等级。
TL; DR:notify()没有做任何事情,而wait()创建了死锁。