我不理解“扎实的Java开发人员”一书中的死锁示例。这种僵局怎么可能?
乍一看,这段代码看起来很明智。您有两个更新发送到单独的线程,每个更新必须在备份线程上进行确认。这似乎并不太奇怪,如果一个线程发生故障,则可能会有另一个线程继续存在。 如果您运行代码,通常会看到一个死锁的示例-两个线程都将报告接收到更新,但两个都不会确认接收到它们作为备份线程的更新。这样做的原因是,在确认方法可以执行之前,每个线程都需要另一个线程释放其持有的锁。
下面是清单4.2中的一个死锁示例
public class MicroBlogNode implements SimpleMicroBlogNode {
private final String ident;
public MicroBlogNode(String ident_) {
ident = ident_;
}
public String getIdent() {
return ident;
}
public synchronized void propagateUpdate(Update upd_, MicroBlogNode
backup_) {
System.out.println(ident + ": recvd: " + upd_.getUpdateText() + " ; backup: " + backup_.getIdent());
backup_.confirmUpdate(this, upd_);
}
public synchronized void confirmUpdate(MicroBlogNode other_, Update
update_) {
System.out.println(ident + ": recvd confirm: " + update_.getUpdateText() + " from " + other_.getIdent()k);
}
public static void main(String[] args) {
final MicroBlogNode local = new MicroBlogNode("localhost:8888");
final MicroBlogNode other = new MicroBlogNode("localhost:8988");
final Update first = getUpdate("1");
final Update second = getUpdate("2");
new Thread(new Runnable() {
public void run() {
local.propagateUpdate(first, other);
}
}).start();
new Thread(new Runnable() {
public void run() {
other.propagateUpdate(second, local);
}
}).start();
}
答案 0 :(得分:3)
第一个线程开始,local.propagateUpdate
被调用,local
现在被锁定,因为该方法已同步。
几乎同时,第二个线程被启动,other.propagateUpdate
被调用,并且实例other
也由于相同的原因而被锁定。
两个线程都愉快地打印文本。在第一个线程中,local
实例尝试通过在confirmUpdate
实例上调用other
与另一个线程进行确认,但是other
仍然被第二个线程锁定-方法尚未返回。
在第二个线程中,other
实例尝试在confirmUpdate
实例上调用local
,但是该实例也被锁定-这次被第一个线程锁定。
local
和other
都在互相等待以释放其锁,并且永远无法解决问题:这是死锁。