哲学家进餐的本质在于互斥访问竞争有限资源
哲学家的生活中有两种交替活动时段:吃饭和思考。当一个哲学家觉得饿了,他就试图分两次去取左右两边的筷子,每次拿一根,但是不分次序。如果成功地得到两根筷子就开始吃饭,吃完放下继续思考。关键问题在于:当哲学家都拿起左边的筷子之后右边没有筷子,则回发生死锁。
如果在拿到左叉后,程序要查看右边的叉子是否可用,如果不可用则放下左边的叉子,等待一段时间,再重复整个过程,但是这种解法也有缺陷,当所有的哲学家都进行这种操作之后,将会一直重复下去,程序在不断运行,但是所有哲学家都没办法获得筷子,这种状态叫做饥饿。
所以下面就要解决这两个问题。
目前看到有下面几种解法:
- 方法1: 最多只允许4位哲学家同时去拿左边的筷子,最终能保证最少有一位哲学家就餐,并且用完释放后供其他人使用。
- 方法2: 规定奇数的哲学家先拿右边的筷子,偶数号的哲学家先拿左边的筷子。
方法1:
标记5根筷子的状态,设置信号量为4,最多只允许4个哲学家同时去拿筷子
#define N 5 //表示5个人
Semaphore chopsticks[5] = {1,1,1,1,1}; //5根筷子的状态,1代表可用
Semaphore mutex = 4; //最多只允许4个哲学家同时拿起左边的筷子
void philosophe(int i) //表示第几个哲学家
{
while(true)
{
think(); //思考
P(mutex);
P((i+N-1)%N); //拿起左边的筷子
P((i+1)%N); //拿起右边的筷子
eating();
V((i+1)%N); //放下左边的筷子
V((i+N-1)%N); //放下右边的筷子
V(mutex);
}
}
方法二:
规定奇数的哲学家先拿右边的筷子,偶数号的哲学家先拿左边的筷子。
#define N 5
Semaphore chopsticks[5] = {1,1,1,1,1};
void philosopher(int i) //i从0开始
{
while(true)
{
think(); //思考
if(i%2==0) //偶数先拿右边的筷子
{
P((i+1)%N); //拿起右边的筷子
P((i+N-1)%N); //拿起左边的筷子
}
else
{
P((i+N-1)%N); //拿起左边的筷子
P((i+1)%N); //拿起右边的筷子
}
eating();
V((i+N-1)%N);
V((i+1)%N);
}
}