死锁产生的四个必要条件:
(1)互斥条件:一个资源每次只能被一个进程使用。
(2)占有且等待:进程已经占有了至少一个资源,同时请求新资源而被阻塞时,对已获得的资源保持不放。
(3)不可强行占有:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
设第i个哲学家,他左边的筷子为i,右边为(i+1)%5
1.加一个同步锁,把并发变为顺序执行
class DiningPhilosophers {
private Object obj = new Object();
public DiningPhilosophers() {
}
// call the run() method of any runnable to execute its code
public void wantsToEat(int philosopher,
Runnable pickLeftFork,
Runnable pickRightFork,
Runnable eat,
Runnable putLeftFork,
Runnable putRightFork) throws InterruptedException {
synchronized(obj){
pickLeftFork.run();
pickRightFork.run();
eat.run();
putLeftFork.run();
putRightFork.run();
}
}
}
感觉类似于同时只允许一个人进餐(?)
2.
class DiningPhilosophers {
private ReentrantLock lock = new ReentrantLock();
private Condition[] conditions = new Condition[5];
private boolean[] forks = new boolean[5];
public DiningPhilosophers() {
for (int i=0;i<5;i++){
conditions[i] = lock.newCondition();
}
}
// call the run() method of any runnable to execute its code
public void wantsToEat(int philosopher,
Runnable pickLeftFork,
Runnable pickRightFork,
Runnable eat,
Runnable putLeftFork,
Runnable putRightFork) throws InterruptedException {
lock.lock();
try{
int leftFork = philosopher;
int rightFork = (philosopher + 1) % 5;
//任意左右叉子被占用,开始等待
while(forks[leftFork]||forks[rightFork]){
conditions[philosopher].await();
}
forks[leftFork]=true;
forks[rightFork]=true;
pickLeftFork.run();
pickRightFork.run();
eat.run();
putLeftFork.run();
forks[leftFork]=false;
conditions[leftFork].signal();
putRightFork.run();
forks[rightFork]=false;
conditions[rightFork].signal();
}
finally{
lock.unlock();
}
}
}
申请筷子得不到满足则放下筷子过段时间再申请