我从oracle那里获得了这个死锁示例代码。
class Thread_Test {
static class Friend {
private final String name;
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public synchronized void bow(Friend bower) {
System.out.format("%s: %s" + " has bowed to me!%n", this.name, bower.getName());
bower.bowBack(this);
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s" + " has bowed back to me!%n", this.name, bower.getName());
}
}
public static void main(String[] args) {
final Friend alphonse = new Friend("Alphonse");
final Friend gaston = new Friend("Gaston");
new Thread(new Runnable() {
public void run() { alphonse.bow(gaston); }
}).start();
new Thread(new Runnable() {
public void run() { gaston.bow(alphonse); }
}).start();
}
}
如果我改变下面的功能弓,我可以解决死锁问题。
public void bow(Friend bower) {
synchronized(this) {
System.out.format("%s: %s" + " has bowed to me!%n", this.name, bower.getName());
}
bower.bowBack(this);
}
我可以使用其他方法来解决此死锁问题。
特别是,我想知道Thread.sleep()可以解决死锁问题以及如何使用它。
你能告诉我Thread.sleep()和其他方法的可能性吗?
非常感谢
答案 0 :(得分:1)
发生死锁是因为发生了以下方法调用:
你的解决方案工作的原因是bowBack(this)调用在同步块之外。
智能使用锁可以更清楚地说明发生死锁的原因和确切位置,并且可以防止死锁。 Java的Semaphore类很好看。
要实际修复它(防止死锁但保持线程安全),你必须扩展问题 - 当Gaston等待Alphonse完成bow()执行他自己的弓()时会发生什么,但是Alphonse需要Gason执行bowBack()完成?一个合理的解决方案是让Gaston在执行bowBack()调用时放弃执行bow()并执行bowBack(),但这完全取决于您尝试解决的问题。
答案 1 :(得分:0)
您需要同时锁定2个对象(让我们称之为A
和B
)。 here是对可能发生的事情的一个很好的解释。要解决这个问题,您可以尝试始终以相同的顺序锁定:
static class Friend {
private static int idCounter;
private final int id;
private final String name;
public Friend(String name) {
this.name = name;
id = idCounter++;
}
public String getName() {
return this.name;
}
public void bow(Friend bower) {
Friend first, second;
if(bower.id > id) {
first = this;
second = bower;
} else {
first = bower;
second = this;
}
synchronized(first) {
synchronized(second) {
System.out.format("%s: %s has bowed to me!%n", this.name,bower.getName());
bower.bowBack(this);
}
}
}
public synchronized void bowBack(Friend bower) {
System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName());
}
}
此处{id {*}} Friend
首先被锁定,因此现在应该发生死锁。