操作系统——最详细讲解经典同步问题(系列三--哲学家就餐问题)

哲学家就餐问题

问题描述:

       一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生的精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,
才试图拿起左、右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲
学家只有同时拿起两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。

问题分析:

      每个哲学家之间拿筷子都是互斥的,如果五个哲学家同时拿筷子则会出现一人一个筷子,则每个哲学家都陷入等待状态而造成死锁。

为了避免死锁现象,可以采取以下三种措施:

  1.  最多允许4个哲学家同时去拿左边的筷子;
  2.  仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子;
  3.  给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之

第一种措施:允许4个哲学家只拿一边的筷子,那么最后一定空余一根筷子,此时离那根筷子近的哲学家就可以拿起剩余的一根筷子吃饭,吃完后释放筷子资源,以便剩余四个哲学家就餐。

第二种措施:五个哲学家随机拿筷子,当五个哲学家中有同时拿到两根筷子的就进行就餐,反之如果都只拿到一根筷子时则全部释放掉筷子重新选取。

第三种措施:这样可以保证一号和二号同时竞争1号筷子,三号和四号同时竞争3号筷子,五号竞争5号筷子。即五位哲学家都先竞争1、3、5奇数号筷子,然后再去竞争剩下的偶数号筷子,这样可以确保一定有哲学家可以拿到两根筷子。

设置互斥信号量数组chopsticka[5]={1,1,1,1,1}表示五根筷子之间互斥访问

伪代码:

//第一种措施:只允许四个哲学家拿筷子
semaphore chopsticks[5]={1,1,1,1,1};//五根筷子之间拿取互斥
semaphore  count=4;//只允许四个哲学家拿筷子
process(){
while(1){
      思考怎么拿筷子;
      p(count);             //进入只允许四个互斥的设定
      p(chopsticks[i]);      //拿左边的筷子
      p(chopsticks[(i+1)%5]);//拿右边的筷子
       拿完筷子就餐;
      v(chopsticks[i]);      //释放左边的筷子
      v(chopsticks[(i+1)%5]); //释放右边的筷子
      v(count);               //离开只允许四个互斥的设定
         }

          }


//第二种措施:必须同时拿到两个筷子才可以进餐
semaphore chopsticks[5]={1,1,1,1,1};//五根筷子之间拿取互斥
semaphore mutex=1;//只允许一个哲学家同时拿两双筷子
process(){
while(1){
      思考怎么拿筷子;
      p(mutex);             //进入只允许一个哲学家同时拿两双筷子的设定
      p(chopsticks[i]);      //拿左边的筷子
      p(chopsticks[(i+1)%5]);//拿右边的筷子
      v(mutex)               //拿完释放该设定,允许其他哲学家进入该设定继续拿筷子
       拿完筷子就餐;
      v(chopsticks[i]);      //释放左边的筷子
      v(chopsticks[(i+1)%5]); //释放右边的筷子            

         }

          }



//第三种措施:奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之
semaphore chopsticks[5]={1,1,1,1,1};//五根筷子之间拿取互斥
process(){
while(1){
      思考怎么拿筷子;
     if(i%2==1)   {          //进入只允许一个哲学家同时拿两双筷子的设定
      p(chopsticks[i]);      //先拿左边的筷子
      p(chopsticks[(i+1)%5]);//后拿右边的筷子
                    }
       else   { 
      p(chopsticks[(i+1)%5]);//先拿右边的筷子
      p(chopsticks[i]);      //后拿左边的筷子
               }     
       拿完筷子就餐;
      v(chopsticks[i]);      //释放左边的筷子
      v(chopsticks[(i+1)%5]); //释放右边的筷子
              
         }

          }

其他进程同步问题以及一些真题练习请看我的其他博客~~

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设计内容: 进程死锁的检测:资源分配图的化简判断是否有死锁发生 设计要求: •建立所需的数据结构。 •从文件中读取资源分配的情况(文件格式自定义)。 •编写资源分配图的化简算法。 •每化简一步,在屏幕上显示化简的当前结果。 •最后给出结论,是否死锁。如果死锁,给出死锁进程和资源。 设计思路: 程序中主要涉及两个方面:进程、资源。两者通过占有和申请发生联系。因此对于每一个进程Pi,建立“占有”和“申请”的数据结构来保存与之相关联的资源(由于事先不知道进程拥有和申请的资源数,故用Vector作为数据结构)。同时记录下程序处理的总的进程数目和资源数目。对于资源,另建立两个数组res和work分别记录第i类资源的总数和当前可用数。 从文件中读入资源和进程的情况时,要进行一些判断。①处理的资源和进程数目不得超过500(500已满足当前实际机器的情况)。②资源及进程的编号不得超过相应的数目也不得小于0。③资源的起始值不应该小于0。 ④起始情况下,所有进程拥有的第i资源总数不应该比其总的资源数目还要多。 由于在理论上已经证明,化简的次序不影响化简的最终结果。所以化简的过程就是不停的寻找满足条件(此进程所申请的资源全部都可以满足)的进程进行化简(即把它拥有的资源加到work数组中),直到不再能找到这样的进程为止。然后检查所有的进程,如果仍有未被化简的进程,则表明死锁已经产生。此时记录下发生死锁的进程编号。然后,为进一步明确哪些进程在哪些资源上发生死锁,给定一个进程入口点采用DFS搜索和次进程相关的所有进程。 为了能在每一步化简后显示当前进程资源的状况,定义了两个画图函数。一个是根据当前资源和进程的“占有”和“申请”状况,画出整体的资源分配图。另一个是在每次化简掉一个进程时删除和它相关的所有边。 程序在VC++6.0中调试、验收通过。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值