zoukankan      html  css  js  c++  java
  • 哲学家就餐问题-中断解决

    哲学家就餐问题是计算机操作系统课程中一定会拿来作为死锁教材的经典案例。问题描述如下:哲学家吃饭问题:哲学家聚在一起吃饭,假定哲学家人数是五,这五个哲学家坐在一张圆桌上面,每个哲学家的左手旁边都放有一个叉子(fork),那么,这围城一圈的五个哲学家有五个叉子。每个哲学家有三种状态,thinking(思考),trying(尝试去拿叉子吃饭),eating(已经拿起叉子,正在吃饭)。每次吃饭需要两个叉子,也就是哲学家左右手边的叉子。如图1所示。

    哲学家吃饭需要两个叉子(吼吼)。

    图1

    本实验采用了两种解决死锁的机制:

    1. 通过定时器(Timer)检测死锁,一旦发生死锁,就将哲学家恢复到初始的状态,然后使得哲学家和叉子的状态恢复到初始状态。
    2. 通过外部中断解决死锁,一旦发生死锁问题,通过外部中断,将哲学家恢复到初始的状态,然后使得哲学家和叉子的状态恢复到初始状态。

    定时器(Timer)代码:

      1 #include <stdio.h>
      2 #include <pthread.h>
      3 #include <stdlib.h> 
      4 #include <sys/wait.h>//为了使用sleep()函数
      5 #include <unistd.h>
      6 #include <signal.h>//为了产生中断
      7  
      8 //哲学家的数目
      9 int  Number;
     10  
     11 //声明共享变量fork,其中fork的数目和哲学家数目是相同的
     12 struct Fork{
     13     int i;//只有0和1两个值,0代表不能被拿起来,1代表可以被拿起来
     14     };
     15 struct Fork  *myfork;
     16 
     17 //定义一个philosopher的三个状态
     18 #define Thinking 1
     19 #define Trying 2
     20 #define Eating 3
     21 
     22 struct State{
     23     int sta;
     24     int left;
     25     int right;
     26     };
     27 struct State *state;
     28 
     29 void *EatMeal();
     30 
     31 
     32 int totalnumber;
     33 void DetectLock(int);
     34 void Sig_hander(int);
     35 
     36 //得到参数
     37 void GetArg(
     38     char* argv[] /*in*/,
     39     int* number /*out*/
     40     );
     41 //统计处于tring状态的哲学家的个数
     42 int tryingNo;
     43 
     44 //拿起叉子
     45 int take_Fork(int i);
     46 //放下叉子
     47 void put_Fork(int i);
     48 
     49 void main(int argc,  char* argv[])
     50 {
     51     GetArg(argv, &Number);
     52     myfork = (struct Fork *)malloc(Number*sizeof(struct Fork));
     53     state = malloc(Number*sizeof(struct State));
     54     
     55     tryingNo = 0;
     56     //声明进程数组,每一个进程代表一个哲学家
     57     pthread_t philosopher[Number];
     58     pthread_t deadLockDetecter;
     59     totalnumber = Number;
     60     /*初始化每个哲学家的状态*/
     61     int t =0;
     62     for(t=0; t< Number; t++)
     63     {
     64         state[t].sta = Thinking;
     65         state[t].left = 0;
     66         state[t].right = 0;
     67     }
     68     
     69     /*初始化每个勺子是可以使用的*/
     70     int k =0;
     71     for(k=0; k<Number; k++)
     72     {
     73         myfork[k].i = 1;
     74     }
     75     
     76     int i;
     77     //创建和哲学家数量想对应的进程,并且每个进程开始进行吃饭的活动
     78     for( i = 0; i < Number; i++)
     79     {
     80         //记录当前进程的编号,并传递到Meal()函数中
     81         int j = i;
     82         pthread_create(&philosopher[i], NULL, EatMeal, &j);
     83         printf("I am philosopher %d
    ", j);
     84     }
     85 
     86     //int k = Number;
     87     pthread_create(&deadLockDetecter,NULL, DetectLock,&k);
     88     
     89     //将所有的进程进行Join操作。
     90     for( i=0; i < Number; i++)
     91     {
     92         pthread_join(philosopher[i], NULL);
     93     }
     94     
     95     //退出程序
     96     pthread_exit(0);
     97     
     98     return ;
     99     
    100 }
    101 
    102 void *EatMeal(int *i)
    103 {
    104     //记录当前的线程id号
    105     int id = *i;
    106 
    107     
    108     state[id].sta = Thinking; //线程初始化的时候为Thinking
    109     
    110     int leftFork = (id + Number) % Number;
    111     int rightFork = (id + Number +1) % Number;
    112     
    113     int mealTime = 5;
    114     int mymealTime = 0;
    115     while (mymealTime < mealTime) //每个philosopher必须吃得符合规定
    116     {
    117         if(state[id].sta == Thinking)
    118         {
    119             sleep(3);    
    120             state[id].sta = Trying;
    121         }else if(state[id].sta == Trying)
    122         {
    123             
    124         //    sleep(1);
    125             if (take_Fork(leftFork))
    126             {
    127                 myfork[leftFork].i = 0;
    128                 state[id].left = 1; //自己标识左边的叉子被自己拿到
    129             //    printf("Phi %d takes left
    ",id);
    130             }
    131             if(take_Fork(rightFork))
    132             {
    133                 myfork[rightFork].i = 0;
    134                 state[id].right = 1; //自己标识一下右边的叉子被自己拿到
    135             //    printf("Phi %d takes right
    ",id);
    136             }
    137                     
    138             printf("Philosopher %d is Trying
    ", id);
    139             sleep(3);
    140             if(!take_Fork(leftFork)&&!take_Fork(rightFork)&&state[id].left==1&& state[id].right==1)
    141             {    
    142                 state[id].sta = Eating; 
    143             }
    144         }
    145         else 
    146         {
    147             printf("Philosopher %d is Eating
    ", id);
    148             sleep(3);
    149             state[id].left=0;
    150             state[id].right=0;
    151             state[id].sta = Thinking;
    152             put_Fork(leftFork);
    153             put_Fork(rightFork);
    154             mymealTime++;
    155 
    156         }
    157     }
    158     
    159 }
    160 
    161 int take_Fork(int forkid)
    162 {
    163     if(myfork[forkid].i==0) return 0;
    164     else 
    165     { 
    166         //myfork[forkid].i = 0;
    167         return 1;
    168     }
    169 }
    170 
    171 void put_Fork(int forkid)
    172 {
    173     if(myfork[forkid].i==0)
    174     {
    175         myfork[forkid].i=1;
    176     }
    177 }
    178 
    179 void GetArg(
    180     char * argv[],
    181     int* number
    182     )
    183 {
    184     *number = strtol(argv[1], NULL, 10);
    185 }
    186 
    187 void DetectLock(
    188     int k)
    189 {
    190     signal(SIGALRM, Sig_hander);
    191     alarm(1);
    192      while(1) pause();
    193 }
    194 
    195 void Sig_hander(int sig)
    196 {
    197     int k = totalnumber;//获取人数
    198     int flag = 1;
    199     int i = 0;
    200     for(i=0; i<k; i++)
    201     {
    202         if(state[i].sta != Trying)
    203         {
    204             flag = 0;
    205         }
    206     }
    207     if(flag == 1)
    208     {
    209         printf("I am timer that dealing with deadlock
    ");
    210         int m = 0;
    211         for(m=0; m<k; m++)
    212         {
    213             state[m].sta = Thinking;
    214             state[m].left = 0;
    215             state[m].right = 0;
    216             myfork[m].i = 1;
    217         }
    218     }
    219 
    220     
    221     alarm(1);
    222     return;
    223     
    224     
    225 }
    View Code

    外部中断代码:

      1 #include <stdio.h>
      2 #include <pthread.h>
      3 #include <stdlib.h> 
      4 #include <sys/wait.h>//为了使用sleep()函数
      5 #include <unistd.h>
      6 #include <signal.h>//为了产生中断
      7  
      8 //哲学家的数目
      9 int  Number;
     10  
     11 //声明共享变量fork,其中fork的数目和哲学家数目是相同的
     12 struct Fork{
     13     int i;//只有0和1两个值,0代表不能被拿起来,1代表可以被拿起来
     14     };
     15 struct Fork  *myfork;
     16 
     17 //定义一个philosopher的三个状态
     18 #define Thinking 1
     19 #define Trying 2
     20 #define Eating 3
     21 
     22 struct State{
     23     int sta;
     24     int left;
     25     int right;
     26     };
     27 struct State *state;
     28 
     29 void *EatMeal();
     30 
     31 
     32 int totalnumber;
     33 void DetectLock(int);
     34 void Sig_hander(int);
     35 
     36 //得到参数
     37 void GetArg(
     38     char* argv[] /*in*/,
     39     int* number /*out*/
     40     );
     41 //统计处于tring状态的哲学家的个数
     42 int tryingNo;
     43 
     44 //拿起叉子
     45 int take_Fork(int i);
     46 //放下叉子
     47 void put_Fork(int i);
     48 
     49 void main(int argc,  char* argv[])
     50 {
     51     GetArg(argv, &Number);
     52     myfork = (struct Fork *)malloc(Number*sizeof(struct Fork));
     53     state = malloc(Number*sizeof(struct State));
     54     
     55     tryingNo = 0;
     56     //声明进程数组,每一个进程代表一个哲学家
     57     pthread_t philosopher[Number];
     58     pthread_t deadLockDetecter;
     59     totalnumber = Number;
     60     /*初始化每个哲学家的状态*/
     61     int t =0;
     62     for(t=0; t< Number; t++)
     63     {
     64         state[t].sta = Thinking;
     65         state[t].left = 0;
     66         state[t].right = 0;
     67     }
     68     
     69     /*初始化每个勺子是可以使用的*/
     70     int k =0;
     71     for(k=0; k<Number; k++)
     72     {
     73         myfork[k].i = 1;
     74     }
     75     
     76     int i;
     77     //创建和哲学家数量想对应的进程,并且每个进程开始进行吃饭的活动
     78     for( i = 0; i < Number; i++)
     79     {
     80         //记录当前进程的编号,并传递到Meal()函数中
     81         int j = i;
     82         pthread_create(&philosopher[i], NULL, EatMeal, &j);
     83         printf("I am philosopher %d
    ", j);
     84     }
     85 
     86     //int k = Number;
     87     pthread_create(&deadLockDetecter,NULL, DetectLock,&k);
     88     
     89     //将所有的进程进行Join操作。
     90     for( i=0; i < Number; i++)
     91     {
     92         pthread_join(philosopher[i], NULL);
     93     }
     94     
     95     //退出程序
     96     pthread_exit(0);
     97     
     98     return ;
     99     
    100 }
    101 
    102 void *EatMeal(int *i)
    103 {
    104     //记录当前的线程id号
    105     int id = *i;
    106 
    107     
    108     state[id].sta = Thinking; //线程初始化的时候为Thinking
    109     
    110     int leftFork = (id + Number) % Number;
    111     int rightFork = (id + Number +1) % Number;
    112     
    113     int mealTime = 5;
    114     int mymealTime = 0;
    115     while (mymealTime < mealTime) //每个philosopher必须吃得符合规定
    116     {
    117         if(state[id].sta == Thinking)
    118         {
    119             sleep(3);    
    120             state[id].sta = Trying;
    121         }else if(state[id].sta == Trying)
    122         {
    123             
    124         //    sleep(1);
    125             if (take_Fork(leftFork))
    126             {
    127                 myfork[leftFork].i = 0;
    128                 state[id].left = 1; //自己标识左边的叉子被自己拿到
    129             //    printf("Phi %d takes left
    ",id);
    130             }
    131             if(take_Fork(rightFork))
    132             {
    133                 myfork[rightFork].i = 0;
    134                 state[id].right = 1; //自己标识一下右边的叉子被自己拿到
    135             //    printf("Phi %d takes right
    ",id);
    136             }
    137                     
    138             printf("Philosopher %d is Trying
    ", id);
    139             sleep(3);
    140             if(!take_Fork(leftFork)&&!take_Fork(rightFork)&&state[id].left==1&& state[id].right==1)
    141             {    
    142                 state[id].sta = Eating; 
    143             }
    144         }
    145         else 
    146         {
    147             printf("Philosopher %d is Eating
    ", id);
    148             sleep(3);
    149             state[id].left=0;
    150             state[id].right=0;
    151             state[id].sta = Thinking;
    152             put_Fork(leftFork);
    153             put_Fork(rightFork);
    154             mymealTime++;
    155 
    156         }
    157     }
    158     
    159 }
    160 
    161 int take_Fork(int forkid)
    162 {
    163     if(myfork[forkid].i==0) return 0;
    164     else 
    165     { 
    166         //myfork[forkid].i = 0;
    167         return 1;
    168     }
    169 }
    170 
    171 void put_Fork(int forkid)
    172 {
    173     if(myfork[forkid].i==0)
    174     {
    175         myfork[forkid].i=1;
    176     }
    177 }
    178 
    179 void GetArg(
    180     char * argv[],
    181     int* number
    182     )
    183 {
    184     *number = strtol(argv[1], NULL, 10);
    185 }
    186 
    187 void DetectLock(
    188     int k)
    189 {
    190     signal(SIGINT, Sig_hander);
    191     sleep(10);
    192     return ;
    193 }
    194 
    195 void Sig_hander(int sig)
    196 {
    197     int k = totalnumber;//获取人数
    198     int flag = 1;
    199     int i = 0;
    200     for(i=0; i<k; i++)
    201     {
    202         if(state[i].sta != Trying)
    203         {
    204             flag = 0;
    205         }
    206     }
    207     if(flag == 1)
    208     {
    209         printf("I am timer that dealing with deadlock
    ");
    210         int m = 0;
    211         for(m=0; m<k; m++)
    212         {
    213             state[m].sta = Thinking;
    214             state[m].left = 0;
    215             state[m].right = 0;
    216             myfork[m].i = 1;
    217         }
    218     }
    219 
    220     return;
    221     
    222     
    223 }
    View Code


    Post Analysis:

    将中断注册到了一个线程中,没有把其写入大主线程中。好吧,这个被老师给黑了。扣分到底!

  • 相关阅读:
    网站添加微信支付功能(小白填坑)
    spring项目中如何添加定时器以及在定时器中自动生成sprng注入对象
    当时间一天天流逝,一个三十岁的屌丝程序员留下了了什么?
    解决使用canvas生成含有微信头像的邀请海报没有微信头像
    jQuery v1.10.2如何判断checkbox(复选框)是否被选中
    调用钉钉接口发送消息
    .net core ajax使用EPPlus上传excle导入总结
    Java企业级权限管理系统的开发总结
    RESTful学习小结
    JS实战(京东秒杀)
  • 原文地址:https://www.cnblogs.com/SevenwindMa/p/3483823.html
Copyright © 2011-2022 走看看