如何修复java中的死锁代码?

时间:2014-08-15 15:30:19

标签: java deadlock

我从oracle那里获得了这个死锁示例代码。

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

如果我改变下面的功能弓,我可以解决死锁问题。

public void bow(Friend bower) {
    synchronized(this) {
        System.out.format("%s: %s" + "  has bowed to me!%n", this.name, bower.getName());
    }
    bower.bowBack(this);
}

我可以使用其他方法来解决此死锁问题。

特别是,我想知道Thread.sleep()可以解决死锁问题以及如何使用它。

你能告诉我Thread.sleep()和其他方法的可能性吗?

非常感谢

2 个答案:

答案 0 :(得分:1)

发生死锁是因为发生了以下方法调用:

  • Alphonse打电话给bow(),得到Alphonse /弓锁
  • Gaston打电话给bow(),得到Gaston / bow lock
  • Alphonse告诉Gaston bowBack(),并等待Gaston完成该行动
  • Gaston告诉Alphonse bowBack(),然后等待Alphonse完成那个动作。
  • 因此,两人都在等待对方完成bowBack()以完成他们的bow(),但是在他们完成bow()之前无法启动他们自己的bowBack()。死锁。

你的解决方案工作的原因是bowBack(this)调用在同步块之外。

智能使用锁可以更清楚地说明发生死锁的原因和确切位置,并且可以防止死锁。 Java的Semaphore类很好看。

要实际修复它(防止死锁但保持线程安全),你必须扩展问题 - 当Gaston等待Alphonse完成bow()执行他自己的弓()时会发生什么,但是Alphonse需要Gason执行bowBack()完成?一个合理的解决方案是让Gaston在执行bowBack()调用时放弃执行bow()并执行bowBack(),但这完全取决于您尝试解决的问题。

答案 1 :(得分:0)

您需要同时锁定2个对象(让我们称之为AB)。 here是对可能发生的事情的一个很好的解释。要解决这个问题,您可以尝试始终以相同的顺序锁定:

static class Friend {
    private static int idCounter;
    private final int id;
    private final String name;

    public Friend(String name) {
        this.name = name;
        id = idCounter++;
    }
    public String getName() {
        return this.name;
    }

    public void bow(Friend bower) {
        Friend first, second;
        if(bower.id > id) {
            first = this;
            second = bower;
        } else {
            first = bower;
            second = this;
        }
        synchronized(first) {
            synchronized(second) {
                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());
    }
}

此处{id {*}} Friend首先被锁定,因此现在应该发生死锁。