java - 这段java代码是如何产生死锁的?

标签 java multithreading deadlock

我正在查看 Oracle 文档以解决死锁问题。 我找到了这段代码

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

我不明白,什么情况下会发生死锁?

我运行了这段代码,它工作得很好。那么一定有一些特殊事件,什么时候会发生死锁?

假设首先在alphonse对象上调用bow,那么当bower.bowBack(this)被调用时,它是否会保留对alphonse对象的锁定在凉亭对象上? 因为如果它保留锁,另一个对象上的 bow 函数将不会获得锁,直到 alphonse 离开它的锁,并且永远不会出现死锁情况。

最佳答案

如果在打印第一行之后、调用 BowBack 之前放置 Thread.sleep(1000),您应该会看到死锁。这种僵局无论如何都可能发生,而且很少见。

您有两个线程,并且以不同的顺序获取两个锁。这可能会使每个线程持有一个锁,但无法获得第二个锁。即陷入僵局。

注意:线程需要很长时间才能启动,这意味着第一个线程可以在第二个线程启动之前运行完成,因此您不太可能会看到该问题。

<小时/>

这是给你的一个谜题。这会造成僵局,你能明白为什么吗?

class A {
    static final int i;
    static {
        i = 128;

        Thread t = new Thread() {
            public void run() {
                System.out.println("i=" + i);
            }
        };
        t.start();
        try {
           t.join();
        } catch (InterruptedException e) {
           Thread.currentThread().interrupt();
        }
    }

关于java - 这段java代码是如何产生死锁的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24653620/

相关文章:

java - 哪种 MySQL 类型最能存储时间点信息 - 日期时间或时间戳

mysql - InnoDB 死锁未提交读! - Java - Glassfish - EJB3 (JPA/Hibernate)

java - 是否是Timer线程导致死锁发生?

java - 没有实现接口(interface)的所有方法。可能吗?

java - 如何在 JUnit 测试中运行 Spring Shell 脚本

java - 如何使用上下文路径访问Tomcat中的应用程序

Python 线程 : What am I missing?(task_done() 调用次数过多)

c++ - 如何使用 `omp parallel` 或其他方式并行化 for 循环?

java - 如何避免在 Java 中忙于自旋

delphi - 关闭线程时死锁