哲学家进餐问题
5 个不讲卫生的哲学家围绕一张圆桌而坐,桌子上放着5 支筷子,每两个哲学家之 间放一支;哲学家的动作包括思考和进餐,进餐时需要同时拿起他左边和右边的两支筷 子,思考时则同时将两支筷子放回原处。
解法一:
semaphore Fork[4]={0,1,2,3,4}; philosopher_i()
{
Thinking;
Being hungry;
P(Fork[i mod 5]);
P(Fork[(i + 1) mod 5]);
Eating;
V(Fork[i mod 5]);
V(Fork[(i + 1) mod 5]);
}
这种解法存在问题,会导致死锁,假如5 个哲学家同时饥饿而各自拿左边的筷子时, 会导致5 个筷子的信号量均为0,当他们试图拿右边的筷子时,都将因没有筷子而无限 等待。对于这种死锁问题,可以采用以下几种解决方法:
1)仅当哲学家的左右筷子均可用时,才允许其进餐。(即用AND 信号量机制解决) 解法如下:
Semaphore array[5]={1,1,1,1,1}; Philosopher_i() //i=0,1,2,3,4 {
While(ture)
{
Think;
Sswait(chopstick[(i+1)mod5],chopstick[i]); Eat;
Ssignal(chopstick[(i+1)mod5],chopstick[i]); }
}
2)
奇数号哲学家先拿左边筷子,然后拿右边筷子;而偶数号哲学家相反。解法如下:
semaphore c[5]={1,1,1,1,1}; 初值均为1;
philosopher_i() //i=0,1,2,3,4 {
If(i mod 2 != 0) //判断是否为奇数号哲学家
{ //若为奇数号哲学家先拿左边筷子
P(c[i]);
P(c[i + 1] mod 5);
Eating;
V(c[i]);
V(c[i + 1] mod 5);
}
else //若为偶数号哲学家先拿右边筷子
{
P(c[i + 1] mod 5);
P(c[i]);
Eating;
V(c[i + 1] mod 5);
V(c[i]);
}
}
关于解决信号量问题的解题思路:
主要是看看进程等的信号和要发出的信号是什么,理清思路。等信号用Wait/P,发信号 用signal/V。
主要步骤是:
(1)分析清楚题目涉及的进程间的制约关系。
(2)设置信号量(包括信号量的个数和初值及其物理含义),合作进程间需要收发几 条消息相应就设置几个信号量。
(3)给出进程相应程序的算法描述或
控制,并把wait、signal 操作加到程序的 适当处。
第一二步是基础、关键,第三步是核心。
掌握实现进程互斥与进程同步的第三步在形式上差异:即wait、signal 操作总是配对 出现的。
但wait,signal 在互斥问题中总是出现在同一个进程的代码中,且紧紧夹着临界区;而 在同步问题中,却是分别出现在两个合作进程的代码中,需要等消息的一方用wait 操作, 相应的对同一信号量的signal 操作则在发出此消息的另一方中。