问题描述:
一群哲学家聚在一起就餐,每两个哲学家之间有一根筷子。每个哲学家需要两根筷子才能用餐,并且一定是先拿起左手边的筷子,然后再拿右手边的筷子。如果所有哲学家在同一时间拿起左手边的筷子,就有可能造成死锁。请使用线程和锁,编写模拟哲学家就餐问题。避免出现死锁。
解法:
首先,先不管死锁,实现哲学家就餐问题。有两个实体,筷子和哲学家。筷子被拿起和被放下与哲学家拿起筷子和放下筷子相对应。我们分别将它们封装成对象。
<pre name="code" class="java">public class Chopstick{
private Lock lock;
public Chopstick(){
lock=new ReentrantLock();
}
public void pickUp(){
lock.lock();
}
public void pickDown(){
lock.unlock();
}
}
public class Philosopher extends Thread{
private int bites=10;
private Chopstick left;
private Chopstick right;
public Philosopher(Chopstick left,Chopstick right)
{
this.left=left;
this.right=right;
}
public void eat(){
pickUp();
chew();
putDown();
}
public void pickUp()
{
left.pickUp();
right.pickUp();
}
public void chew(){}
public void putDown()
{
left.putDown();
right.putDown();
}
public void run()
{
for(int i=0;i<bites;i++)
{
eat();
}
}
}
上面的程序,当哲学家都拿起左边的筷子,等待着右边的筷子,就有可能发生死锁。
为了预防死锁,当哲学家拿不到右边的筷子时,就让他放下已拿到的左边的筷子。
public class Chopstick{
private Lock lock;
public Chopstick(){
lock=new ReentrantLock();
}
public boolean pickUp(){
lock.tryLock();
}
public void pickDown(){
lock.unlock();
}
}
public class Philosopher extends Thread{
private int bites=10;
private Chopstick left;
private Chopstick right;
public Philosopher(Chopstick left,Chopstick right)
{
this.left=left;
this.right=right;
}
public void eat(){
if(pickUp()){
chew();
putDown();
}
}
public boolean pickUp()
{
if(!left.pickUp())return false;
if(!right.pickUp())
{
left.putDown();
return false;
}
return true;
}
public void chew(){}
public void putDown()
{
left.putDown();
right.putDown();
}
public void run()
{
for(int i=0;i<bites;i++)
{
eat();
}
}
}
参看书籍:程序员面试金典