Java Sun教程中关于死锁的问题

Java Sun教程中关于死锁的问题,java,Java,下面是Sun教程中描述死锁的直接代码。然而,考虑到这两种方法都是同步的,我不理解在这种情况下死锁是如何发生的。两个线程如何同时位于同一个同步方法中? 死锁描述了两个或多个线程被永远阻塞,彼此等待的情况。这里有一个例子 阿尔方斯和加斯顿是朋友,非常相信礼貌。礼貌的一条严格规则是,当你向朋友鞠躬时,你必须保持鞠躬,直到你的朋友有机会回敬你。不幸的是,这条规则没有考虑到两个朋友同时向对方鞠躬的可能性。此示例应用程序死锁模拟了这种可能性: public class Deadlock { stat

下面是Sun教程中描述死锁的直接代码。然而,考虑到这两种方法都是同步的,我不理解在这种情况下死锁是如何发生的。两个线程如何同时位于同一个同步方法中?

死锁描述了两个或多个线程被永远阻塞,彼此等待的情况。这里有一个例子

阿尔方斯和加斯顿是朋友,非常相信礼貌。礼貌的一条严格规则是,当你向朋友鞠躬时,你必须保持鞠躬,直到你的朋友有机会回敬你。不幸的是,这条规则没有考虑到两个朋友同时向对方鞠躬的可能性。此示例应用程序死锁模拟了这种可能性:

public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        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());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse = new Friend("Alphonse");
        final Friend gaston = new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}
当死锁运行时,两个线程在试图调用bowBack时极有可能都会阻塞。两个块都不会结束,因为每个线程都在等待另一个退出

同步(实例)方法锁定对象,而不是类

阿尔方斯。鲍抓住了阿尔方斯和加斯顿的锁。鲍抓住了加斯顿的锁。当“阿尔方斯”线在船头时,它试图抓住船头“加斯顿”的锁。同样,“加斯顿”试图抓住“阿尔方斯”的锁

为清晰起见进行编辑(我希望):

让我们将这两个线程称为Thread1和Thread2

Thread1运行alphonse.bow(gaston),在那里它抓住alphonse对象上的锁,而Thread2运行gaston.bow(alphonse)并抓住gaston对象上的锁

在Thread1中,当它尝试运行bower.bowBack(this),其中bower=gaston时,线程需要首先获得gaston上的锁

在此过程中,Thread2尝试使用bower=alphonse执行相同的操作。Thread1有一个Thread2需要的锁,反之亦然,这就是死锁发生的原因


顺便说一句,死锁不一定总是会发生。如果Thread1可以在Thread2有机会启动和完成之前启动和完成(例如,如果在Thread1启动后但在Thread2创建/启动之前挂起主线程),则不会发生死锁

阿尔方斯是如何试图锁定加斯顿的。阿尔方斯总是使用阿尔方斯实例。我不明白下面的“当‘阿尔方斯’线程在bow中时,它试图抓住bower.bowBack中‘gaston’上的锁。“阿尔方斯’如何试图锁定gaston实例。第一个线程称为alphonse.bow(gaston))。此时,线程在alphonse上有一个锁。一旦这个方法到达bower.bowBack,bower就是gaston,它就会试图锁定gaston。我所说的“阿尔方斯”是指“阿尔方斯弓(加斯顿)”的线;对不起,如果不清楚的话。啊……我现在明白了。在凉亭里。弓背(这个);鲍尔=加斯顿-出于某种原因,我认为鲍尔可能是阿尔方斯的复制品