我正在阅读Oracle的Java Concurrency Tutorial。
还有一个DeadLock
的例子核心代码:
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());
}
然后当教程转到LockObject时,它提供了一个解决方案来处理Lock Object的死锁。
现在我想知道是否有一种替代方法可以在不使用Lock
对象的情况下避免死锁?
答案 0 :(得分:3)
避免死锁的一种方法是通过强加获取两个锁的顺序来打破对称性。例如,你可能会说,当启动一个弓时,线程应该始终锁定名字首先按字母顺序排列的朋友,这样任何执行弓箭的线程必须首先获得对Alphonse的锁定然后锁定Gaston,从不相反:
public void bow(Friend bower) {
Friend lock = (this.name.compareTo(bower.name)<0)? this : bower);
synchronized (lock) {
System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName());
bower.bowBack(this);
}
}
public void bowBack(Friend bower) {
Friend lock = (this.name.compareTo(bower.name)>0)? this : bower);
synchronized (lock) {
System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName());
}
}
无锁选项是使用原子变量来表示弓是否已经在进行中,如果有弓,则等待:
private static AtomicBoolean bowing = new AtomicBoolean();
public void bow(Friend bower) {
while (!bowing.compareAndSet(false, true)) Thread.yield();
System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName());
bower.bowBack(this);
bowing.set(false);
}
另一种避免死锁的方法是使用单个锁而不是两个;竞争单个锁的两个线程无法死锁。
private static Object lock = new Object();
public void bow(Friend bower) {
synchronized (lock) {
System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName());
bower.bowBack(this);
}
}
public void bowBack(Friend bower) {
synchronized (lock) {
System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName());
}
}