我们该怎么做才能克服活锁? (一般而言,具体到下面提供的代码示例)

时间:2016-02-18 12:48:29

标签: java livelock

我是Java的新手,正在尝试学习活锁的概念。

我找到了一个很好的在线活锁的例子,丈夫和妻子正在尝试吃汤,但他们之间只有一把勺子。每个配偶都过于礼貌,如果另一个尚未吃掉,他们会通过勺子。

我的问题是,我们应该采取什么措施来克服一般情况下的活锁问题?在这个特定的例子中?我希望修改我的代码以演示问题的解决方案。

public class Livelock {
    static class Spoon {
        private Diner owner;
        public Spoon(Diner d) { owner = d; }
        public Diner getOwner() { return owner; }
        public synchronized void setOwner(Diner d) { owner = d; }
        public synchronized void use() { 
            System.out.printf("%s has eaten!", owner.name); 
        }
    }

    static class Diner {
        private String name;
        private boolean isHungry;

        public Diner(String n) { name = n; isHungry = true; }       
        public String getName() { return name; }
        public boolean isHungry() { return isHungry; }

        public void eatWith(Spoon spoon, Diner spouse) {
            while (isHungry) {
                // Don't have the spoon, so wait patiently for spouse.
                if (spoon.owner != this) {
                    try { Thread.sleep(1); } 
                    catch(InterruptedException e) { continue; }
                    continue;
                }                       

                // If spouse is hungry, insist upon passing the spoon.
                if (spouse.isHungry()) {                    
                    System.out.printf(
                        "%s: You eat first my darling %s!%n", 
                        name, spouse.getName());
                    spoon.setOwner(spouse);
                    continue;
                }

                // Spouse wasn't hungry, so finally eat
                spoon.use();
                isHungry = false;               
                System.out.printf(
                    "%s: I am stuffed, my darling %s!%n", 
                    name, spouse.getName());                
                spoon.setOwner(spouse);
            }
        }
    }

    public static void main(String[] args) {
        final Diner husband = new Diner("Bob");
        final Diner wife = new Diner("Alice");

        final Spoon s = new Spoon(husband);

        new Thread(new Runnable() { 
            public void run() { husband.eatWith(s, wife); }   
        }).start();

        new Thread(new Runnable() { 
            public void run() { wife.eatWith(s, husband); } 
        }).start();
    }
}

1 个答案:

答案 0 :(得分:1)

一般来说,没有通用的解决方案。

如果未检测到进度,则线程必须停止重复相同的操作。

在你的例子中允许配偶不止一次吃(从而发现所爱的人没有吃过而且没有进展,因为只吃了一步)应该强迫勺子的主人吃。

显然,现实生活场景将更加精细,但检测零进展并采取与正常情况不同的行为至关重要。