死锁 - 在这个例子中是如何发生的?

任何人都可以解释:

  1. 为什么我们会陷入僵局?
  2. 加斯顿如何在阿方斯退出该功能之前进入功能弓?(它应该从函数返回才能退出函数 - or)?bowBack()bow()

这是我得到的输出 - 然后程序卡住了!

阿方斯: 加斯顿向我鞠躬了!

加斯顿: 阿方斯向我鞠躬了!

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();
    }
} 

答案 1

块 / 方法同步到 ,即调用块 / 方法的对象实例。(因为“对象实例”将替换为“类实例”。synchronizedthisstatic

这是你的2个对象与自己同步,而不是一个公共对象。

试试下面这样:

public class Deadlock {
   static class Friend {
      private final String name;
      public Friend(String name) {
         this.name = name;
      }
      public String getName() {
         return this.name;
      }
      public void bow(Friend bower) {
         synchronized (getClass()) {
            System.out.format("%s: %s  has bowed to me!%n", this.name, bower.getName());
            bower.bowBack(this);
         }
      }
      public void bowBack(Friend bower) {
         synchronized (getClass()) {
            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();
   }
}

答案 2

线程 1:实例被锁定,从中打印一行,然后调用(但由于下面调用的同步实例,从线程 2 锁定)alphonsealphonse.bow(gaston);gaston.bowBack()gastonbow()

线程 2:实例被锁定,从中打印一行,然后调用(但由于在其上调用了同步实例,因此从线程 1 锁定)gastongaston.bow(alphonse);alphonse.bowBack()alphonsebow()

因此,他们都在等待发布并且无法退出方法,因此死锁bow()