Concurrency 下面的代码中死锁是如何发生的?

Concurrency 下面的代码中死锁是如何发生的?,concurrency,deadlock,Concurrency,Deadlock,我试图从Oracle的网站上了解死锁,但不确定两个自定义线程何时进入死锁状态 package com.geekthread.java.threads; public class DeadLock { static class Friend { private final String name; public Friend(String name) { this.name = name; } public String getName() {

我试图从Oracle的网站上了解死锁,但不确定两个自定义线程何时进入死锁状态

package com.geekthread.java.threads;

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");
         //holds lock for alphonse            
      new Thread(new Runnable() {
        public void run() { alphonse.bow(gaston); }
    }).start();
    //holds lock for gastone
    new Thread(new Runnable() {
        public void run() { gaston.bow(alphonse); }
    }).start();
}
}
}

请纠正我对上述计划的理解:-

1.)持有阿尔方斯的锁

new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
2.)为加斯通持有锁

new Thread(new Runnable() {
                public void run() { gaston.bow(alphonse); }
            }).start();

我尝试从bowback中删除synchronized关键字,该关键字不会在死锁情况下结束,即程序执行完成,程序在执行后终止


谢谢

我肯定不是Java方面的专家,但我的猜测是:

由于类友元是静态的,因此类友元的方法是静态的。因此,这些方法锁定类本身,而不是类的对象


这将提供更多的细节:

每个对象都有一个与其关联的锁,也称为隐式锁或监视器锁。当
synchronized
用于示例中的方法时,线程将尝试获取与该方法的对象关联的锁。因此,运行
alphonse.bow(加斯顿)的线程将获取与alphonse对象关联的锁

大致在同一时间,运行
gaston.bow(阿尔方斯)的线程
将获取与gaston对象关联的锁

所以你有阿尔方斯线程持有阿尔方斯对象的锁,加斯顿线程持有加斯顿对象的锁

当alphonse现在尝试执行
bower.bowBack(这个),请注意,“bower”指的是gaston对象。因此,alphonse正在尝试执行gaston对象的
bowBack
方法。由于bowBack方法是同步的,alphonse需要获得gaston对象锁才能继续。但是当然gaston线程已经有了gaston对象锁

因此,alphonse正在尝试执行gaston的bowBack方法,但无法执行,因为它无法获得gaston对象锁

与此同时,加斯顿也有同样的问题。他需要调用alphonse的bowBack方法,但是alphonse线程已经有了alphonse对象锁

因此,每个线程都有一个锁,并试图获得另一个线程已经拥有的锁,而这两个线程都无法继续-这是一个典型的死锁场景


编辑:从
bowBack
中删除“synchronized”可以防止死锁,正如您所发现的,因为现在没有任何东西可以阻止alphonse线程调用gaston的
bowBack
方法-alphonse不再需要获得gaston持有的gaston对象锁。同样的逻辑反过来适用于gaston,gaston也可以继续。

这是错误的:“因为类友元是静态的,类友元的方法是静态的”类是静态的,因此我们可以在同一个文件中有多个类。如果
Friend
在它自己的
Friend.java
文件中,而不是static@dkatzel谢谢不知道java的静态类概念。