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

这个java代码是如何产生死锁的?,java,multithreading,deadlock,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.

我正在查看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(此)
在bower对象上调用时,它是否会在
alphonse
对象上保持锁定? 因为如果它保留了锁,
bow
函数在另一个对象上不会得到锁,直到
alphonse
离开它的锁,并且永远不会出现死锁情况。

如果你放一个线程。sleep(1000)在打印第一行之后,在调用bowBack之前,你应该会看到死锁。这种僵局可能会发生,这将是罕见的

您有两个线程和两个锁被获取是不同的顺序。这会使每个线程持有一个锁,但无法获得第二个锁。i、 僵局

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


这是给你的拼图游戏。这会造成死锁,你知道为什么吗

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

在处理多线程时,两个线程中的操作可能以任何顺序发生。所以想象一下,在这种情况下,两个参与者都执行
bow
,然后他们都尝试执行
bow\u back
。由于
bow
bow\u back
处于同步状态,两个对象都将被锁定,您将无法对其中任何一个对象执行
bow\u back
。两个对象都将等待,直到另一个对象“自由”,这不会发生,因为
弓在“向后弓”之前不会返回。

在弓A和G的末尾调用bowBack,导致A调用G.bow,G调用A.bow,而A和G的弓是同步的。所以它们都在等待对方完成。

你有两个对象,阿尔方斯和加斯顿,还有两个线程,线程1和线程2

假设发生这种情况:

  • Thread1:alphonse进入bow()方法。并将锁定阿尔方斯物体

  • Thread2:gaston进入bow()方法。并将在加斯顿物体上保持一把锁

  • Thread1:alphonse在bow()方法中调用gaston对象上的bowBack()

    ->Thread1将阻塞,因为Thread2已锁定gaston

  • Thread2:gaston在bow()方法中调用alphonse对象上的bowBack()

    ->Thread2将被阻止,因为Thread1已经锁定了alphonse


  • 现在Thread1正在等待Thread2。Thread2正在等待Thread1。这是一个死锁。

    如果双方同时进入
    bow()
    方法,或者在

    System.out.println();
    
    如果您没有看到这两条“已向我鞠躬!”消息,则会发生死锁

    如果第一个线程在第二个线程启动之前终止,则不会出现死锁

    使用Thread.sleep(1000)扩展代码


    然后两个线程都进入bow()并解除锁定。

    您认为它运行良好是什么意思,请发布输出,可能您认为它运行良好,这就是死锁!“向我鞠躬”的信息在哪里?对不起,有时它会给阿尔方斯:加斯顿向我鞠躬了!加斯顿:阿尔方斯向我鞠躬了!加斯顿:阿尔方斯向我鞠躬了!阿尔方斯:加斯顿向我鞠躬了!有时阿尔方斯:加斯顿向我鞠躬了!加斯顿:阿尔方斯向我鞠躬了@是的,你是对的,有时是死锁,有时是不可能复制的,我看没有问题,除了这一行Thread.currentThread().interrupt();在接球区?但我不明白有人能解释这个问题吗?或者我想我将不得不把它作为另一个问题发布,因为现在它让我好奇地想知道答案?类和静态块的加载是隐式的
    同步的
    ,这意味着在初始化一个类时,你不能在另一个线程中访问该类中的任何内容。在这种情况下,初始化正在等待使用
    a.i
    的线程,即等待第一个线程完成静态块。
    public synchronized void bow(Friend bower) {
    System.out.println(....);
    Thread.sleep(1000);
    ...
    }