哲学家就餐问题描述
哲学家就餐问题是指,有五个哲学家围坐一桌,每两个哲学家之间都有一只叉子,一共有五只叉子。每个哲学家都只有两个动作,即思考和就餐,哲学家思考的时候不需要任何的资源,但只有同时拿起他左右的两只叉子,才能开始进餐。进餐完毕后将叉子放归原位。这个问题在于,应该如何保证哲学家们的动作有序进行,如不会出现有人永远拿不到叉子的情况。
一些初步的尝试
第一次尝试
对哲学家就餐问题进行分析,可以发现,相邻的两个哲学家对他们中间的叉子应该是互斥访问的。为此,为每个叉子设置一个信号量,每个哲学家在进餐之间,首先需要获得其左右两个叉子,即分别对其左右的两只叉子做一次P
操作;进餐完毕后,将两只叉子放归原位,即分别对其左右两只叉子做一次V
操作。实现的伪代码如下:
Semaphore forks[5];
for(fork : forks)
fork.sem = 1; //initialize to 1
#define LEFT (i - 1 + 5) % 5
#define RIGHT (i + 1) % 5
//for philosopher i
void philosopher(){
while(true){
thinking();
forks[LEFT].P();
forks[RIGHT].V();
eating();
forks[LEFT].V();
forks[RIGHT].V();
}
}
容易看出,这种实现方法是有问题的,倘若所有五个哲学家同时想要进餐,有一种情况是他们都分别拿起了他们左边的叉子,这样所有哲学家想要获得右边的叉子时都会失败而进入阻塞状态,并且这种阻塞将一直进行下去,因为没有哲学家会主动释放已经获得的叉子,即出现了