规定在拿到左侧的筷子后,先检查右面的筷子是否可用。如果不可用,则先放下左侧筷子, 等一段时间再重复整个过程。 分析:当出现以下情形,在某一个瞬间,所有的哲学家都同时启动这个算法,拿起左侧的筷 子,而看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此 这样永远重复下去。对于这种情况,所有的程序都在运行,但却无法取得进展,即出现饥饿, 所有的哲学家都吃不上饭。 (2) 描述一种没有人饿死(永远拿不到筷子)算法。 考虑了四种实现的方式(A、B、C、D): A.原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释 放出他所使用过的两支筷子,从而可使更多的哲学家进餐。以下将room 作为信号量,只允 许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入 餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会 出现饿死和死锁的现象。 伪码: semaphore chopstick[5]=; semaphore room=4; void philosopher(int i) } B.原理:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐。 方法1:利用AND 型信号量机制实现:根据课程讲述,在一个原语中,将一段代码同时需 要的多个临界资源,要么全部分配给它,要么一个都不分配,因此不会出现死锁的情形。当 某些资源不够时阻塞调用进程;由于等待队列的存在,使得对资源的请求满足FIFO 的要求, 因此不会出现饥饿的情形。 伪码: semaphore chopstick[5]=; void philosopher(int I) } 方法2:利用信号量的保护机制实现。通过信号量mutex对eat()之前的取左侧和右侧筷 子的操作进行保护,使之成为一个原子操作,这样可以防止死锁的出现。 伪码: semaphore mutex = 1 ; semaphore chopstick[5]=; void philosopher(int I) }
package philosopher;
public class Chopsticks {
String name;
boolean Enable=true;
public Chopsticks(String name){
this.name=name;
}
//拿起筷子 不能用则等待
public synchronized void pickUp(){
while(this.Enable==false){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
this.Enable=false;
}
}
//放下筷子
public synchronized void putDown(){
this.Enable=true;
this.notifyAll();
}
/**
* 多线程 三个人吃面条 坐一圆桌 每两人见有一根筷子 每个人只能拿到左边和右边的筷子 吃面条必须用两根筷子 ,
* 用多线程实现他们吃面条的过程 ,每个人都要吃饱,每个人吃饭时间随机
* */
public static void main(String[] args) {
Chopsticks chops1=new Chopsticks("筷子1");
Chopsticks chops2=new Chopsticks("筷子2");
Chopsticks chops3=new Chopsticks("筷子3");
Chopsticks chops4=new Chopsticks("筷子4");
Chopsticks chops5=new Chopsticks("筷子5");
Philosopher philo1=new Philosopher("哲学家1", chops1, chops2);
Philosopher philo2=new Philosopher("哲学家2", chops2, chops3);
Philosopher philo3=new Philosopher("哲学家3", chops3, chops4);
Philosopher philo4=new Philosopher("哲学家4", chops4, chops5);
Philosopher philo5=new Philosopher("哲学家5", chops5, chops1);
philo1.start();
philo2.start();
philo3.start();
philo4.start();
philo5.start();
}
}
package philosopher;
public class Philosopher extends Thread{
String name;
Chopsticks left,right;
public Philosopher(String name,Chopsticks l,Chopsticks r){
this.name=name;
left=l;
right=r;
}
public void run(){
left.pickUp();
System.out.println(name+"拿起了"+left.name);
right.pickUp();
System.out.println(name+"拿起了"+right.name);
System.out.println(name+"可以吃饭了");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"吃饱了,放下了"+left.name+"和"+right.name);
left.putDown();
right.putDown();
}
}