当前位置: 首页 > 面试题库 >

此Java代码如何产生死锁?

顾喜
2023-03-14
问题内容

我正在通过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
,那么alphonsebower.bowBack(this)在bower对象上调用bow时,它会在对象上保持锁定吗?因为如果它保留其锁定,则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();
        }
    }


 类似资料:
  • 问题内容: 我需要在功能中锁定两个对象,当前代码看起来像这样; 如您所见,如果另一个线程使用obj1和两个相反的代码运行这段代码,则这是死锁的简单明了的配方。 有没有一种方法可以使用concurrency-utils锁来避免这种情况? 我当时正在考虑维护一个对象及其锁的地图,并验证它们是否可供使用,但是似乎无法提出一种可以预测锁顺序的干净方法。 问题答案: 尽管您保留了锁定顺序,但是如果将obj1

  • 问题内容: 我想知道Java如何处理以下情况: 假设我有一个名为Debug的类,它看起来像这样: 并假设我的代码有一个看起来像这样的调用: 我有几个问题: 如果 isAssertEnabled 标志设置为 false ,是否将整个对Debug.assertTrue的调用编译出来?请注意,仅在调用函数后才检查isAssertEnabled == true。 如果整个调用确实被编译出来了,是否也意味着

  • 问题内容: 下面的代码在执行时会产生堆栈溢出错误。但是,如果删除其中一个 它运行时没有堆栈溢出错误。如果我有以上两行,而类中只有其中一行,则没有错误,怎么会出现堆栈溢出错误呢? 问题答案: 两者都需要生成一个。当包含此行时: 首次访问该类时,将创建的实例。 不包括此行: 一切都很好。但是这条线很关键。每次创建的实例时,它都会尝试初始化其成员变量-另一个对象。然后, 该 实例将 其 初始化为另一个对

  • @Bean public WebMvcEndpoint HandlerMap webEndpoint ServletHandlerMap(WebEndpoint供应商webEndpoint供应商,ServletEndpoint供应商servletEndpoint供应商,控制器Endpoint供应商控制器Endpoint供应商,Endpoint MediaTypes endpoint MediaTy

  • 有人知道如何在Java代码中实现这个SQL代码吗? 时间格式类似于数据库中的36000,然后在这个sql命令之后是:10:00 我想让这个函数在Java中工作,而不是在SQL中工作。

  • 问题内容: 据我了解,Java编译器生成“字节代码”,而不是“目标代码”。首先,这是正确的吗? 而且,这就是我的书所说的,我想知道为什么这是正确的。字节码和目标码有什么区别? 问题答案: 字节代码只是Java虚拟机的“目标代码”。它不是 本机 代码(例如x86)。老实说,这些天我很少听到“目标代码”一词-用更具体的术语讲通常更清晰。