扎实的Java开发人员中的Java死锁示例

时间:2018-07-31 23:00:11

标签: java concurrency

我不理解“扎实的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();
}

1 个答案:

答案 0 :(得分:3)

第一个线程开始,local.propagateUpdate被调用,local现在被锁定,因为该方法已同步。

几乎同时,第二个线程被启动,other.propagateUpdate被调用,并且实例other也由于相同的原因而被锁定。

两个线程都愉快地打印文本。在第一个线程中,local实例尝试通过在confirmUpdate实例上调用other与另一个线程进行确认,但是other仍然被第二个线程锁定-方法尚未返回。

在第二个线程中,other实例尝试在confirmUpdate实例上调用local,但是该实例也被锁定-这次被第一个线程锁定。

localother都在互相等待以释放其锁,并且永远无法解决问题:这是死锁。