这不是Java, Multithreading with synchronized methods的重复......他没有问同样的问题。
我正在尝试编写一个使用多线程和死锁的程序。我无法理解在我的synchronized方法中如何以及在何处使用wait()和notify()来让线程等待并使用notify()将其唤醒。我让它在ping语句之后使第一个线程等待,所以下一个线程也将启动它的ping语句。但我有一个notify()唤醒第一个线程,我无法弄清楚为什么线程不会唤醒。以下是我的输出:
Starting...1
Girl (ping): pinging Boy
Boy (ping): pinging Girl
Girl (ping): asking Boy to confirm
Boy (confirm): confirm to Girl
Girl (ping): got confirmation
Boy (ping): asking Girl to confirm
Girl (confirm): confirm to Boy
Boy (ping): got confirmation
我的代码是死锁,或者我没有正确使用等待和通知,因为它停在这里:
Starting...1
Girl (ping): pinging Boy
Boy (ping): pinging Girl
Girl (ping): asking Boy to confirm
Boy (confirm): confirm to Girl
Girl (ping): got confirmation
这是我的代码:
Monitor.java
class Monitor {
String name;
public Monitor (String name) { this.name = name; }
public String getName() { return this.name; }
public synchronized void ping (Monitor p) {
p.release(p);
System.out.println(this.name + " (ping): pinging " + p.getName());
notify();
try { wait(); } catch (Exception e) {}
System.out.println(this.name + " (ping): asking " + p.getName() + " to confirm");
p.confirm(p);
System.out.println(this.name + " (ping): got confirmation");
}
public synchronized void confirm (Monitor p) {
System.out.println(this.name + " (confirm): confirm to " + p.getName());
}
public synchronized void release (Monitor p) {
notify();
}
}
Runner.java
public class Runner extends Thread {
Monitor m1, m2;
public Runner (Monitor m1, Monitor m2) {
this.m1 = m1;
this.m2 = m2;
}
public void run () {
m1.ping(m2);
}
}
Deadlock.java
public class DeadLock {
public static void main (String args[]) {
int i=1;
System.out.println("Starting..."+(i++));
Monitor a = new Monitor("Girl");
Monitor b = new Monitor("Boy");
(new Runner(a, b)).start();
(new Runner(b, a)).start();
}
}
答案 0 :(得分:1)
您正在致电:
(new Runner(a, b)).start();
// which effectively calls in run()
a.ping(b);
此锁定a
会在a
上调用通知,然后等待a
。
另一个线程调用:
(new Runner(b, a)).start();
// which effectively calls in run()
b.ping(a);
此锁定b
会在b
上调用通知,然后等待b
。
由于两个线程都没有通知另一个线程,因此它们永远不会离开该状态。我不确定你要完成什么,所以很难弄清楚如何修复代码。
修改强>
现在你已经编辑了代码,你有一个更标准的死锁。
a
然后尝试锁定b
以通知它。b
然后尝试锁定a
以通知它。每个线程都有锁,但需要另一个锁才能继续。经典僵局。
我建议您学习使用调试器@ OhioState22。设置断点并逐步执行代码。这是一个不错的Eclipse tutorial。
答案 1 :(得分:0)
通常避免使用Java的wait()和notify(),而是选择Java 5的并发功能之一,例如ReentrantLock的。原因是如果一个线程在你的线程命中wait()之前调用notify(),那么对wait()的后续调用将会无限期地阻塞并取决于你的算法。查找RenetrantLock
的javadoc