我们应该怎么做才能克服活锁呢? (一般和特定于下面提供的代码示例)
What should we do to overcome livelock? (in general and specific to the code example provided below)
我是 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 个步骤)应该迫使勺子的主人只进食。
显然,现实生活中的场景会更加复杂,但检测零进度并采取与正常情况不同的行动至关重要。
我是 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 个步骤)应该迫使勺子的主人只进食。
显然,现实生活中的场景会更加复杂,但检测零进度并采取与正常情况不同的行动至关重要。