java - Sun教程中关于死锁的一个问题

标签 java

下面是直接来自描述死锁的 Sun 教程的代码。但是,考虑到两种方法都是同步的,我不明白在这种情况下如何发生死锁。两个线程如何同时在同一个同步方法中?

死锁描述了两个或多个线程永远阻塞,互相等待的情况。这是一个例子。

Alphonse 和 Gaston 是 friend ,而且非常讲究礼貌。一个严格的礼貌规则是,当你向 friend 鞠躬时,你必须一直鞠躬,直到你的 friend 有机会还礼。不幸的是,这条规则没有考虑到两个 friend 可能同时互相鞠躬的可能性。这个示例应用程序 Deadlock 模拟了这种可能性:

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

当死锁运行时,两个线程极有可能在尝试调用 bowBack 时阻塞。两个 block 都不会结束,因为每个线程都在等待另一个线程退出 bow。

最佳答案

同步(实例)方法锁定对象,而不是类。

alphonse.bow 获取了 alphonse 的锁,gaston.bow 获取了 gaston 的锁。当“alphonse”线程处于 bow 状态时,它会尝试在 bower.bowBack 上获取“gaston”上的锁。同样,“gaston”试图获取“alphonse”的锁。

为清楚起见编辑(我希望):

我们称这两个线程为 Thread1 和 Thread2。

Thread1 运行 alphonse.bow(gaston),它在其中获取 alphonse 对象的锁,而 Thread2 运行 gaston.bow(alphonse) 并获取 gaston 对象的锁。

在 Thread1 中,当它尝试运行 bower.bowBack(this) 时,其中 bower = gaston,线程需要首先获取 gaston 上的锁。

在此过程中,线程 2 尝试使用 bower = alphonse 做同样的事情。 Thread1 有 Thread2 需要的锁,反之亦然,这就是发生死锁的原因。

顺便说一句,死锁不一定总是会发生。如果 Thread1 可以在 Thread2 有机会这样做之前启动和完成(例如,如果在 Thread1 启动之后但在创建/启动 Thread2 之前挂起主线程),则不会发生死锁。

关于java - Sun教程中关于死锁的一个问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2270930/

相关文章:

java - 在 Java 中由 UUID 生成唯一数字?

java - 如何关闭 eclipse 中某些文件夹(如 node_modules)的 javascript 验证(包括 tern/lint/jshint)?

java - IPC 的 RMI 替代品?

java - 从文件中读取字节后,大多数是正确的,除了 1 是错误的和负的

java - 如何在没有数据库连接的情况下部署Spring应用程序

java - 在多个计算节点上运行相同的Java程序

Java IE - 用于 Java 的 Internet Explorer

java - 当 SAME 方法在 Java 中不返回值时,Lambda 会返回一个值

java - 'synchronized' 真的只是语法糖吗?

java - 将图像和按钮添加到 JPanel 上