在Java教程中,我来到了这个简单的死锁示例,由于某种原因,我无法弄清它为何被阻塞

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());
            System.out.println("Nice try " + this.name);
            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();
    }
}


让我们看看一些真实的例子

run:
Alphonse: Gaston  has bowed to me!
Gaston: Alphonse  has bowed to me!
Nice try Gaston
Nice try Alphonse


因此,现在运行“ bow()”的Alphonse和Gaston都在“ bow()”末尾试图互相调用“ bowBack()”,“ bowBack()”不是静态的,因此Alphonse和加斯顿已经分离了该方法的实例,之前也没有调用过“ bowBack()”,因此不应阻塞该方法。那么为什么是僵局。

在教程中
http://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

它被解释为

When Deadlock runs, it's extremely likely that both threads will block when they
attempt to invoke bowBack. Neither block will ever end, because each thread is
waiting for the other to exit bow.


但是为什么要运行“ bowBack()”,如果它们彼此不干扰,则应首先等待“ bow()”的结尾

Alphonse.bow()--->尝试致电-> Gaston.bowBack()

Gaston.bow()--->尝试致电-> Alphonse.bowBack()

最佳答案

但是为什么要运行“ bowBack()”,如果它们彼此不干扰,则应首先等待“ bow()”的结尾


调用bowBack()时-正在运行的线程尝试获取的锁是Object正在尝试调用其方法的锁。

在这里-阿方斯是一个对象,加斯顿是第二个对象。

Alphonse.bow()--->尝试致电-> Gaston.bowBack()

在上面的代码中,第一个呼叫在Alphonse上锁定,并且在该锁定仍然保持的同时,尝试在Gaston上获取锁定。

因此,在线程1中:锁定(Alp)并尝试在不释放Lock(Apl)的情况下锁定(Gaston)

Gaston.bow()--->尝试致电-> Alphonse.bowBack()

在这里,第一个bow()获取对Gaston对象的锁定,然后尝试获取对Alphonse的锁定。

因此,在线程2中:锁定(Gaston)并尝试不释放锁定(Gaston)的锁定(Apl)

如果线程1和线程2中的第一步都已完成,那么您可以得出结论,第二步将永远无法完成-因此出现了死锁

07-24 15:15