解决Java中死锁的替代方案



我正在阅读Oracle的Java Concurrency Tutorial。

还有一个死锁的例子

核心代码:

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

然后,当本教程转到 LockObject 时,它提供了一个解决方案来处理 Lock 对象的死锁。

现在我想知道是否有另一种方法可以在不使用Lock对象的情况下避免死锁?

避免死锁的一种方法是通过强加获取两个锁的顺序来打破对称性。例如,你可以说,在开始弓时,线应该总是在名字按字母顺序排在第一位的朋友上锁,这样任何做弓的线都必须首先获得阿尔方斯的锁,然后获得加斯顿的锁,永远不要反向:

    public void bow(Friend bower) {
        Friend lock = (this.name.compareTo(bower.name)<0)? this : bower);
        synchronized (lock) {
            System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName());
            bower.bowBack(this);
        }
    }
    public void bowBack(Friend bower) {
        Friend lock = (this.name.compareTo(bower.name)>0)? this : bower);
        synchronized (lock) {
            System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName());
        }
    }

无锁选项是使用原子变量来指示弓是否已经在进行中,如果有弓,请等待:

    private static AtomicBoolean bowing = new AtomicBoolean();
    public void bow(Friend bower) {
        while (!bowing.compareAndSet(false, true)) Thread.yield();
        System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName());
        bower.bowBack(this);
        bowing.set(false);
    }
避免死锁

的另一种方法是使用单个锁而不是两个锁;两个线程竞争单个锁不能死锁。

    private static Object lock = new Object();
    public void bow(Friend bower) {
        synchronized (lock) {
            System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName());
            bower.bowBack(this);
        }
    }
    public void bowBack(Friend bower) {
        synchronized (lock) {
            System.out.format("%s: %s has bowed back to me!%n", this.name, bower.getName());
        }
    }

最新更新