1

我正在阅读Oracle 的Java 并发教程

还有一个死锁的例子

核心代码:

    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 Object的死锁。

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

4

1 回答 1

3

避免死锁的一种方法是通过强制获取两个锁的顺序来破坏对称性。例如,您可能会说,在启动弓箭时,线程应该始终锁定名字按字母顺序排在第一位的朋友,因此任何做弓箭的线程都必须先获得 Alphonse 的锁,然后再获得 Gaston 的锁,从不相反:

    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());
        }
    }
于 2013-09-27T02:19:51.863 回答