目录
1. 问题描述
有五个亚洲哲学家共用一张圆桌(怜师闭关中),他们的生活方式是交替地进行思考和就餐。在圆桌上有五根筷子,哲学家饥饿时便试图取用其左右最靠近她的筷子,只有在她拿到两只筷子时才能进餐。进餐毕,放下筷子继续思考。
2. 问题分析
每根筷子都是临界资源,在一段时间内只允许一位哲学家使用。因此,使用互斥型信号量来表示每根筷子。其描述如下:
semaphore chopstick[5] = {1, 1, 1, 1, 1};
考虑到 semaphore 的结构,实际应该写成以下形式:
semaphore chopstick[5];
for(int i = 0; i < 5; ++i)
semaphore chopstick[i].value = 1;
3. 利用记录型信号量解决哲学家就餐问题
当哲学家饥饿时,总是先去拿她左边的筷子,执行成功后,再去拿她右边的筷子:
wait(chopstick[i]); //拿起左筷子
wait(chopstick[(i+1)%5]); //拿起右筷子
进餐毕,又先放下她左边的筷子,再放下她右边的筷子:
signal(chopstick[i]);
signal(chopstick[(i+1)%5]);
则第 i 位哲学家的活动可描述为:
do {
wait(chopstick[i]); //拿起左筷子
wait(chopstick[(i+1)%5]); //拿起右筷子
//eat
signal(chopstick[i]);
signal(chopstick[(i+1)%5]);
//think
} while(true);
但有可能引起死锁:假如五位哲学家同时饥饿而各自拿起左边的筷子时,就会使五个信号量 chopstick 均为 0;当她们再试图去拿右边的筷子时,都将因无筷子可拿而无限期地等待。
可采取以下几种解决方法:
1)至多允许有四位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐,并在用餐完毕时能释放出她用过的两根筷子,从而使更多的哲学家能够进餐。
姐姐们同时拿起了左边的筷子,Leeseo 不能再拿筷子了。这时小圆还能拿起右边的筷子,并在用餐完毕时释放出她用过的两根筷子,从而使更多的哲学家能够进餐。
2)仅当哲学家的左、右两根筷子均可用时,才允许她拿起筷子进餐。
按照这种方法来思考,则将上图解释为安叮叮在和 Leeseo、Liz 争夺筷子的比赛中胜利,顺利拿到两根筷子;同理,秋天前辈也争夺到了两根筷子。
3)规定奇数号哲学家先拿起她左边的筷子,然后再去拿右边的筷子;而偶数号哲学家则相反。
没人和安叮叮抢筷子,因此她顺利得到左筷子;Liz 和秋天前辈抢筷子;小圆和 Leeseo 抢筷子。假设秋天前辈和小圆抢到了筷子,则 Liz 和 Leeseo 由于没有抢到第一根筷子而退出比赛。安叮叮顺利拿到右筷子,秋天前辈和小圆再来争夺 4 号筷子。最终总有一位哲学家能获得两根筷子进餐。
当 Liz 和 Leeseo 均抢到时只会有一位哲学家能进餐,因为 Leeseo 的右筷子早被安叮叮拿了。
4. 利用 AND 信号量解决哲学家就餐问题
利用 AND 信号量就是上述方法中的第二种,即一次性将左右筷子都分配给哲学家,只要有一根筷子没有分配到,那另一根筷子也不分配给她。由于 Swait 和 Ssignal 操作是原子操作,所以率先去抢的哲学家一定能获得两根筷子。
semaphore chopstick[5] = {1, 1, 1, 1, 1};
do {
Swait(chopstick[i], chopstick[(i+1)%5]);
//eat
Ssignal(chopstick[i], chopstick[(i+1)%5]);
//think
} while(true);