【发布时间】:2014-12-04 16:34:20
【问题描述】:
这是Oracle关于Lock对象的java教程中的例子。请有人确认我是否正确解释了代码。
我将只考虑第一个线程,因为其他线程的工作方式相同。
首先,它获取alphonse的锁,并访问方法impendingBow。该方法现在尝试将两个实例的两个锁分配给线程。如果线程不能同时获得两个锁,它会释放它获得的那个。这是我卡住的时候。如果线程释放锁,另一个线程可以访问这两个实例,并且第一个线程应该在释放锁后立即停止执行。但实际上并没有。它仍然返回布尔值并继续在 bow 方法中运行 else 语句。为什么它可能发生?我认为就像同步代码一样,线程应该停止执行,直到它再次获得锁。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;
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 (int n = 0; n <5;n++) {
try {
Thread.sleep(Math.round(Math.random()*1000));
} catch (InterruptedException e) {}
bowee.bow(bower);
}
}
}
public static void main(String[] args) {
final Friend alphonse =
new Friend("Alphonse");
final Friend gaston =
new Friend("Gaston");
new Thread(new BowLoop(alphonse, gaston)).start();
new Thread(new BowLoop(gaston, alphonse)).start();
}
}
【问题讨论】:
-
是什么让你认为线程应该在释放
Lock对象后停止执行? -
我把锁对象和同步代码联系起来,它只允许线程在获得锁时运行代码,如果没有则阻塞线程。
-
不运行如何获取锁?
-
反过来是我的问题,为什么它释放了锁但仍然运行。如果一个线程在同步代码中运行,我并不反对,它已经获得了锁。但我不确定锁定对象。
-
锁用于包围关键部分,因此一次只有一个线程可以访问该部分。如果一个线程释放了一个锁,那么它就不再处于临界区并且不应该等待任何东西。
标签: java synchronization deadlock