为什么Java同步方法会出现死锁?

问题描述 投票:0回答:1
public static void main(String[] args) { 
    final Friend aaa = new Friend("AAA"); 
    final Friend bbb = new Friend("BBB");
    new Thread(new Runnable() {public void run() { aaa.push(bbb); }}).start();
    new Thread(new Runnable() {public void run() { bbb.push(aaa); }}).start();
}

static class Friend {
    private final String name;
    public Friend(String name) {
        this.name = name;
    }
    public String getName() {
        return this.name;
    }
    public synchronized void push(Friend friend) {
        for (int i = 0; i < 3; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {}
            System.out.format(i + " - %s: %s"  + " pushed me!%n", this.name, friend.getName());
        }
        
        friend.pushBack(this);
    }
    public synchronized void pushBack(Friend bower) {
        System.out.format("%s: %s" + " pushed back to me!%n",this.name, bower.getName());
    }
}

0 - AAA: BBB pushed me!

0 - BBB: AAA pushed me!

1 - BBB: AAA pushed me!

1 - AAA: BBB pushed me!

2 - AAA: BBB pushed me!

2 - BBB: AAA pushed me!

我的理解是synchronized方法只允许一个线程同时运行,那为什么打印结果是这样的呢?我认为bbb应该先等待aaa完成push方法。

为什么会因为同步方法pushBack而发生死锁?

java multithreading deadlock synchronized
1个回答
0
投票

出现死锁的原因是因为你的两个线程正在互相等待。

流程如下:

  • 线程 1 在
    push
    上调用
    AAA
    。它获取了
    AAA
    上的锁。
    同时,线程 2 在
    push
    上调用
    BBB
    。它获取了
    BBB
    上的锁。
  • 在循环结束时,线程 1 在
    pushBack
    上调用
    BBB
    。它尝试获取
    BBB
    上的锁,但线程 2 仍然拥有该锁。
    同时,线程 2 在
    pushBack
    上调用
    AAA
    。它尝试获取
    AAA
    上的锁,但线程 1 仍然拥有该锁。

线程 1 现在正在等待线程 2 持有的锁,而线程 2 现在正在等待线程 1 持有的锁。两者都不会释放其锁,因此出现死锁。

在这种流程中,您的代码想要以不同的顺序获取一个或多个对象的锁,这是导致死锁的最常见原因之一。在大多数情况下,解决方案是使用固定顺序。

© www.soinside.com 2019 - 2024. All rights reserved.