如何检查此示例中的死锁

How to check deadlock in this example

目前我正在学习死锁,我发现了一个死锁的例子,但我不明白这个例子中的死锁是如何发生的。

public class Main {

    public static void main(String[] args) {
        final PolitePerson jane = new PolitePerson("Jane");
        final PolitePerson john = new PolitePerson("John");

        new Thread(new Runnable() {
            @Override
            public void run() {
                 jane.sayHello(john);
            }
        }).start();

       new Thread(new Runnable() {
            @Override
            public void run() {
                john.sayHello(jane);
            }
        }).start();
    }

    static class PolitePerson {
        private final String name;

        public PolitePerson(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public synchronized void sayHello(PolitePerson person){
            System.out.format("%s: %s" + " has said hello to me!%n", this.name, person.getName());

            person.sayHelloBack(this);
        }

        public synchronized void sayHelloBack(PolitePerson person) {
            System.out.format("%s: %s" + " has said hello back to me!%n", this.name, person.getName());
        }
    }
}

我花了一个多小时了解这里发生的事情,但没有明白。 这是我得到的输出

Jane: John has said hello to me!
John: Jane has said hello to me!

或者我在这里误解了同步。

标有synchronized 的方法使用this 作为锁锁定critical-section(方法)。要进入临界区(并锁定它),线程需要获取相应的锁。如果section已经加锁,则线程阻塞在入口处,等待释放锁。

A 和 B 是线程:

  • A 调用 jane.sayHello(john) 并锁定 jane
  • B 调用 john.sayHello(jane) 并锁定 john.

请注意 sayHello 标记为 synchronized

  • A 调用 person.sayHelloBack(this),其中 personjohn
  • B 调用 person.sayHelloBack(this),其中 personjane

注意 sayHelloBack 也标有 synchronized

  • B持有john,所以A的调用john.sayHelloBack被阻塞

  • A持有jane,所以B的调用jane.sayHelloBack被屏蔽

  • A正在等待B释放锁,反之亦然

  • 死锁。

当我们将方法标记为 synchronized 时,它会锁定当前对象。因此,第一个线程在对象 jane 上锁定,而第二个线程在调用方法 sayHello().

后立即锁定对象 john

由于您已将 sayHelloBack() 也标记为同步,它会一直等到其他线程释放对调用对象的锁定。对于第一个线程,它调用 john.sayHelloBack(),它尝试获取 john 上的锁 - 但它已被 thread-2 获取。对于第二个线程,它调用 jane.sayHellpBack(),它尝试获取 jane 上的锁 - 但它已被 thread-1.

获取

因此,两个线程都在等待锁,导致死锁。