说来也是有趣,我完全是被代码带笑了。
什么是活锁?
线程没有阻塞,始终在运行,但是程序始终得不到进展,因为线程始终做重复的同样的事情。
假设有这样一堆恩爱夫妻,贫困年代,大家条件不好,有了吃的互相谦让,过于谦让,一张纸谦让,就会导致活锁。就是线程一直在运行,事情却没有任何进展。
和死锁相比,活锁更害人,因为活锁一直在消耗CPU资源,而死锁会阻塞。
定义一个 勺子类:
static class Spoon{
private Diner owner;
public synchronized void use(){
System.out.printf("%s has eaten!",owner.name);
}
public Diner getOwner() {
return owner;
}
public void setOwner(Diner owner) {
this.owner = owner;
}
public Spoon(Diner owner) {
this.owner = owner;
}
}
定义一个食客:
static class Diner{
private String name;
private boolean isHungry=true;
public void eatWith(Spoon spoon,Diner spouse){
while (isHungry){
if (spoon.owner!=this){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
continue;
}
//此处是逻辑错误点
if (spouse.isHungry){
System.out.println(name+":亲爱的"+spouse.name+"你先吃吧.");
spoon.setOwner(spouse);
continue;
}
spoon.use();
isHungry=false;
System.out.println(name+":Ok,我吃完了");
spoon.setOwner(spouse);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Diner(String name) {
this.name = name;
}
}
恩爱夫妻跑起来:
Diner husband=new Diner("牛郎");
Diner wife=new Diner("织女");
Spoon spoon=new Spoon(husband);
new Thread(new Runnable() {
@Override
public void run() {
husband.eatWith(spoon,wife);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
wife.eatWith(spoon,husband);
}
}).start();
这样的代码运行后,只会是无限的进行下去。
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
Process finished with exit code -1
Process finished with exit code -1 是因为代码被我强行停止了,两个人互相谦让而导致一直说话,都吃不上饭。
解决活锁的办法:
加入随机因素是其中一个办法。
在谦让勺子的时候,加入随机数。
Random random=new Random();
if (spouse.isHungry&&random.nextInt(10)<9){
System.out.println(name+":亲爱的"+spouse.name+"你先吃吧.");
spoon.setOwner(spouse);
continue;
}
那么运行就是这样了。
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女:亲爱的牛郎你先吃吧.
牛郎:亲爱的织女你先吃吧.
织女 has eaten!织女:Ok,我吃完了
牛郎 has eaten!牛郎:Ok,我吃完了
Process finished with exit code 0