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();
    }
}这个不是已经synchronized了吗?为什么第二个线程还能抢占进来。如何修改才能解开死锁这个问题呢?谢谢

解决方案 »

  1.   

    首先,假设alphonse线程先获得CPU权限执行
    alphonse会调用
    alphonse.bow(gaston);  此时,alphonse对象被锁住 --1
    而bow方法里,会调用
    bower.bowBack(this); --A 这里的bower就是参数gaston,this就是alphonse假设在调用--A之前,gaston线程获得CPU权限而执行
    那么gaston会调用gaston.bow(alphonse); 此时,gaston对象被锁住 --2
    而bow方法里,会调用
    bower.bowBack(this); --B 这里的bower就是参数alphonse,this就是gaston假设这个时候alphonse获得CPU权限继续执行--A,因为gaston对象被锁住,所以--A要等待gaston对象的锁被释放,而要释放gaston对象锁,就需要gaston线程执行的gaston.bow(alphonse); 方法结束(即--2结束),而该方法中调用--B--B要执行就需要获得alphonse对象锁,而alphonse对象锁被--1锁住,这样就造成--1要调用结束就要等待--2,而--2要调用结束就要等待--1,也就是造成死锁
    解决方法很多,主要是看你想怎么做,只要避开互相等待对方的锁就可以了
    最简单的做法就是两个方法都去掉synchronized,因为这里并不是一个线程调用一个方法,另一个调用另一个方法,也就是说,两个线程都是直接调用相同的一个方法,而且方法属于不同的对象,所以没必要严格的把两个方法对同一个对象同步,如果目的是想把两个方法串行,即所谓的两个方法的打印同步,那么可以锁住相同的一个对象就可以了
    比如public void bow(Friend bower) {
        synchronized(Deadlock.class) { //两个线程锁同一个对象,这里偷懒,作为例子直接锁类对象
            System.out.format("%s: %s has bowed to me!%n",  
            this.name, bower.getName());
            bower.bowBack(this);
         }
      }public void bowBack(Friend bower) { //这里可以不要synchronized
        //或者可以跟上面一样shchronized(Deadlock.class),
        //因为线程不直接调用这个方法,所以上面的方法锁住了,这里也就自然同步了,所以synchronized可不要
        System.out.format("%s: %s has bowed back to me!%n",
        this.name, bower.getName());
    }