以下代码使用Lock对象以避免死锁情况。
在函数impendingBow中,2个对象如何同时获得锁定: 当前的对象和朋友的凉亭?
myLock = lock.tryLock();
yourLock = bower.lock.tryLock();
是因为它有两个不同的对象吗? 如果是的话,这是否足以让一个锁用于少量物体?
这是完整的代码:
public class Safelock {
static class Friend {
private final String name;
private final Lock lock = new ReentrantLock();
public Friend(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public boolean impendingBow(Friend bower) {
Boolean myLock = false;
Boolean yourLock = false;
try {
myLock = lock.tryLock();
yourLock = bower.lock.tryLock();
} finally {
if (! (myLock && yourLock)) {
if (myLock) {
lock.unlock();
}
if (yourLock) {
bower.lock.unlock();
}
}
}
return myLock && yourLock;
}
public void bow(Friend bower) {
if (impendingBow(bower)) {
try {
System.out.format("%s: %s has"
+ " bowed to me!%n",
this.name, bower.getName());
bower.bowBack(this);
} finally {
lock.unlock();
bower.lock.unlock();
}
} else {
System.out.format("%s: %s started"
+ " to bow to me, but saw that"
+ " I was already bowing to"
+ " him.%n",
this.name, bower.getName());
}
}
public void bowBack(Friend bower) {
System.out.format("%s: %s has" +
" bowed back to me!%n",
this.name, bower.getName());
}
}
static class BowLoop implements Runnable {
private Friend bower;
private Friend bowee;
public BowLoop(Friend bower, Friend bowee) {
this.bower = bower;
this.bowee = bowee;
}
public void run() {
Random random = new Random();
for (;;) {
try {
Thread.sleep(random.nextInt(10));
} catch (InterruptedException e) {}
bowee.bow(bower);
}
}
}
答案 0 :(得分:1)
2个对象如何同时获得锁
两个对象意味着两个独立的锁。没有什么时候被称为巨型锁。有很多单独的锁。
是因为它是2个不同的对象吗?如果是的话,是否意味着对一些对象使用一个锁就足够了
是的,如果您有一组需要同步修改的对象,则只能使用一个锁。在这种情况下,您可以选择任何对象或新的专用对象作为组的锁。
任何人都可以解释我们如何在此实现中避免死锁?
为避免死锁,您必须始终以相同的顺序锁定对象。这就是你所做的,所以你的程序没有死锁。更确切地说,当你有两个锁A和B时,你的一个线程可以锁定A然后B或B(A可能已经或可能没有被另一个线程锁定)或仅A(B可能已经或可能不已经被另一个线程锁定)。在这些情况下永远不会出现僵局。如果你的一个线程可以锁定B然后A,那么就会出现死锁。事实并非如此。
避免死锁的好方法是在锁上编写依赖图。每个锁都是此图中的一个对象,依赖关系是通过线程以特定顺序获取可能的锁。然后,要获得死锁,必须有一个有wait-for graph的循环。但是因为等待图是你的依赖图的子图,并且因为你的依赖图没有循环,所以不可能有死锁。
答案 1 :(得分:0)
这里有两个不同的锁定实例,因此取一个不会干扰另一个。
当一个线程获取锁定X并且另一个线程获取锁定Y时发生死锁。然后第一个线程尝试获取锁定Y,并等待它被释放。同时,第二个线程尝试获取锁X,并等待它被释放。由于两个线程都在相互等待,因此操作永远无法完成,并且线程处于死锁状态。
这里,代码使用tryLock
,如果无法获取锁,则不等待。相反,它会立即返回false
。由于线程在获取锁之前不会阻塞,因此该代码段永远不会导致死锁。