哲学家就餐问题-中断解决


哲学家就餐问题是计算机操作系统课程中一定会拿来作为死锁教材的经典案例。问题描述如下:哲学家吃饭问题:哲学家聚在一起吃饭,假定哲学家人数是五,这五个哲学家坐在一张圆桌上面,每个哲学家的左手旁边都放有一个叉子(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\n", 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\n",id);
130             }
131             if(take_Fork(rightFork))
132             {
133                 myfork[rightFork].i = 0;
134                 state[id].right = 1; //自己标识一下右边的叉子被自己拿到
135             //    printf("Phi %d takes right\n",id);
136             }
137                     
138             printf("Philosopher %d is Trying\n", 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\n", 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\n");
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\n", 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\n",id);
130             }
131             if(take_Fork(rightFork))
132             {
133                 myfork[rightFork].i = 0;
134                 state[id].right = 1; //自己标识一下右边的叉子被自己拿到
135             //    printf("Phi %d takes right\n",id);
136             }
137                     
138             printf("Philosopher %d is Trying\n", 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\n", 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\n");
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:

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

优质内容筛选与推荐>>
1、NHK SHV 的 22.2 声道音频系统
2、华为测试用例模板简写
3、Android 开发之旅:短信的收发及在android模拟器之间实践(一)
4、词频统计
5、回文序列


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn