美文网首页
【专项专攻】01-哲学家进餐问题

【专项专攻】01-哲学家进餐问题

作者: 创造new_world | 来源:发表于2019-06-17 18:14 被阅读0次

前言:

image.png

当一位哲学家思考时,他与其他同事不交流。时而,他会感到饥饿,并试图拿起与他相近的两根筷子(筷子在他和他的左或右邻居之间)。一个哲学家一次只能拿起一根筷子。显然,他不能从其他哲学家手里拿走筷子。当一个饥饿的哲学家同时拥有两根筷子时,他就能吃。在吃完后,他会放下两根筷子,并开始思考。

哲学家就餐问题是一个经典的同步问题,这不是因为其本身的实际重要性,也不是因为计算机科学家不喜欢哲学家,而是因为它是大量并发控制问题的一个例子。这个代表型的例子满足:在多个进程之间分配多个资源,而且不会出现死锁和饥饿。

哲学家进餐问题:
(一)问题:
5个哲学家围坐在一个圆桌上,每两个哲学家之间都有一只筷子,哲学家平时进行思考,只有当他们饥饿时,才拿起筷子吃饭。
规定每个哲学家只能先取其左边筷子,然后取其右边筷子,然后才可以吃饭。

(二)分析:
每一只筷子都是一个临界资源,设置5个互斥信号量。
Semaphore stcik[5]={1,1,1,1,1}

因为:只有占有左边筷子-》占有右边筷子-》吃饭
所以p(左边筷子)-》p(右边筷子)-》吃饭

(三)实现:
main(){
philosopher(0);//注意不可以用循环,因为此中是4个并列的进程。
philosopher(1);
philosopher(2);
philosopher(3);
philosopher(4);
}

philosopher(int i){
while(1){
思考;
p(stick[i]);//取左边筷子
p(stick[i+1]);//取右边筷子

进餐;
V(stick[i]);
v(stick[i+1]);
}
}

(四)问题:
如果5个哲学家同时拿起自己左边的筷子,就会发生死锁。

(五)防止死锁的方法:

(1)方法一:
规定在拿到左侧的筷子后,先检查右面的筷子是否可用。如果不可用,则先放下左侧筷子, 等一段时间再重复整个过程。

问题:发生饥饿现象;
如果同时拿起左边筷子,则右边的筷子都不可用,则放下,然后再次拿起,。。。,则谁都无法就餐,

(2)方法二:
最多允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释
放出他所使用过的两支筷子,从而可使更多的哲学家进餐。

伪码:
semaphore chopstick[5]={1,1,1,1,1};
semaphore room=4;
void philosopher(int i)
{
while(true)
{
think();
wait(room); //请求进入房间进餐
wait(chopstick[i]); //请求左手边的筷子
wait(chopstick[(i+1)%5]); //请求右手边的筷子
eat();
signal(chopstick[(i+1)%5]); //释放右手边的筷子
signal(chopstick[i]); //释放左手边的筷子
signal(room); //退出房间释放信号量room
}
}

(3)将拿左筷子,与拿右筷子当做一个原子操作:(即只有当左右筷子均可以拿到时,才拿筷子。)

方法一:
利用AND 型信号量机制实现:根据课程讲述,在一个原语中,将一段代码同时需
要的多个临界资源,要么全部分配给它,要么一个都不分配,因此不会出现死锁的情形。

伪码:
semaphore chopstick[5]={1,1,1,1,1};
void philosopher(int I)
{
while(true)
{
think();
P(chopstick[(I+1)]%5,chopstick[I]);
eat();
V(chopstick[(I+1)]%5,chopstick[I]);
}
}

方法二:
利用信号量的保护机制实现。通过信号量mutex对eat()之前的取左侧和右侧筷
子的操作进行保护,使之成为一个原子操作,这样可以防止死锁的出现。

伪码:
semaphore mutex = 1 ;
semaphore chopstick[5]={1,1,1,1,1};
void philosopher(int I)
{
while(true)
{
think();
P(mutex);
P(chopstick[(I+1)]%5);
P(chopstick[I]);
V(mutex);

eat();
V(chopstick[(I+1)]%5);
V(chopstick[I]);
}
}

(4)规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号 的哲学家则相反。
伪码:
semaphore chopstick[5]={1,1,1,1,1};
void philosopher(int i)
{
while(true)
{
think();
if(i%2 == 0) //偶数哲学家,先右后左。
{
P (chopstick[ i + 1 ] mod 5) ;
P (chopstick[ i]) ;
eat();
V (chopstick[ i + 1 ] mod 5) ;
V (chopstick[ i]) ;
}
Else //奇数哲学家,先左后右。
{
p (chopstick[ i]) ;
p (chopstick[ i + 1 ] mod 5) ;
eat();
V (chopstick[ i]) ;
V (chopstick[ i + 1 ] mod 5) ;
}
}

相关文章

  • 【专项专攻】01-哲学家进餐问题

    前言: 当一位哲学家思考时,他与其他同事不交流。时而,他会感到饥饿,并试图拿起与他相近的两根筷子(筷子在他和他的左...

  • 哲学家进餐问题

    1965年,荷兰计算机科学家图灵奖得主Edsger Wybe Dijkstra提出并解决了一个他称之为哲学家进餐的...

  • 哲学家进餐问题

    问题描述 一张圆桌旁坐了五个哲学家,每两名哲学家中间有一根筷子,每个哲学家面前有一碗米饭。哲学家重复的做思考和进餐...

  • 哲学家进餐问题

    哲学家进餐问题是著名的死锁问题,5个哲学家,5根筷子,每个哲学家进餐需要获得左右两根筷子才可以; 信号量 使用信号...

  • 经典PIC问题

    哲学家进餐: 哲学家问题可出现拿起左边的筷子,然后拿起右边的筷子进餐,但是假如五个哲学家同时拿起左边的筷子,那么右...

  • 哲学家进餐

    哲学家进餐 VC++相关演示,本源码演示了线程同步算法的哲学家进餐问题,说明:本程序是操作系统中比较典型的线程同步...

  • windows下 c 实现哲学家进餐问题

  • Java 死锁分类

    1. 死锁简介 经典的“哲学家进餐”问题很好的描述了死锁的情况。5个哲学家吃中餐,坐在一张圆桌上,有5根筷子,每个...

  • 线程同步导致的问题死锁哲学家进餐问题

    请关注我的微信公众号 个人微信公众号 技术交流群 (仅作技术交流):642646237 ​请关注我的头条号: 线程...

  • 8.2 经典进程同步问题-哲学家进餐问题

    问题描述 一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生精力用...

网友评论

      本文标题:【专项专攻】01-哲学家进餐问题

      本文链接:https://www.haomeiwen.com/subject/irjzfctx.html