使用Java中的同步方法进行死锁

时间:2018-02-25 14:06:46

标签: java multithreading concurrency deadlock

此代码来自Oracle tutorial关于并发性。我不明白为什么同步方法导致deadlock。当方法不是synchronized时,一切正常,但是当我添加synchronized关键字时,程序停止并且永远不会调用方法bowBack()。有人能以负担得起的方式解释为什么会这样吗下面提到了代码段:

public class Deadlock {
    static class Friend {
        private final String name;

        Friend(String name) {
            this.name = name;
        }

        String getName() {
            return this.name;
        }

        synchronized void bow(Friend bower) {
            System.out.format("%s: %s"
                        + "  has bowed to me!%n",
                this.name, bower.getName());
            bower.bowBack(this);
        }

        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(() -> alphonse.bow(gaston)).start();
        new Thread(() -> gaston.bow(alphonse)).start();
    }
}

2 个答案:

答案 0 :(得分:4)

  • 主题1:alphonse.bow(gaston) - >线程1保持对alphonse的锁定,因为bow()是同步的
  • 主题2:gaston.bow(alphonse) - >线程2持有gaston上的锁,因为bow()是同步的
  • 主题1:gaston.bowBack(alphonse) - >块,因为bowBack是同步的,因此线程1需要获得已经由线程2保持的gaston锁
  • 主题2:alphonse.bowBack(gaston) - >块,因为bowBack是同步的,因此线程2需要获得已经由线程1保持的alphonse锁

因此两个线程都被阻塞,等待另一个线程释放锁定。

答案 1 :(得分:1)

synchronized方法意味着它锁定正在运行它的对象实例。

因此,当您在每个bow上调用Friend时,它会自行锁定。 然后,每个Friend实例尝试bowBack,但另一个实例被其自己bow锁定,因此无法调用。

在这种情况下,两个线程都在等待资源解锁。由于他们实际上正在等待彼此的资源,这是一个僵局。