在使用java中的sychronized或者显示锁来进行互斥操作时,就可能会出现死锁的情况:即任务一获得A资源,等待B资源。任务二获得B资源等待C资源。任务三获得C资源等待D资源。而任务四获得D资源等待A资源,这样就造成一个连续的循环等待,没有哪个线程能够继续下去,称为死锁。
对于死锁,哲学家就餐问题就是一个经典的例子。
问题描述[1]:
在一个圆桌上,有n个哲学家,n只筷子,每个哲学家左右两边各返一只筷子。哲学家可以进行思考和吃饭,思考时,不获取筷子。吃饭时,必须同时获得左右两只筷子才能吃饭(先获得右边,再获得左边)。
先来看看chopstick类:
package philosopher;
/**
* 满足:
* 每根筷子同时只能被一个哲学家获得,若有另外一个哲学家请求获得该筷子,则需要等待
* 哲学家使用完筷子之后就放回并通知其他哲学家使用
* @author lecky
*
*/
public class Chopstick {
private int index;
private boolean use = false;
public Chopstick(int index) {
super();
this.index = index;
}
@Override
public String toString() {
return "Chopstick [index=" + index + "]";
}
/*
* 获得筷子
* 该筷子被获得之后,当有其他哲学家线程来请求获得时,都需要等待
*/
public synchronized void take() throws InterruptedException{
while(use)
wait();
use =true;
}
/*
* 归还筷子
* 当持有该筷子的哲学家使用完毕之后,就将其归还,并通知其他在等待该筷子资源的哲学家
*/
public synchronized void drop(){
use = false;
notifyAll();
}
}
Philosopher类:
哲学家先获得右边的筷子,再获得左边的筷子。在获得左边的筷子时,若左边的筷子已经被相邻哲学家获得,则需要等待直到其释放该资源为止,即left.take()会阻塞,直到被通知。
package philosopher;
import<