哲学家就餐问题是计算机操作系统课程中一定会拿来作为死锁教材的经典案例。问题描述如下:哲学家吃饭问题:哲学家聚在一起吃饭,假定哲学家人数是五,这五个哲学家坐在一张圆桌上面,每个哲学家的左手旁边都放有一个叉子(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:

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

转载于:https://www.cnblogs.com/SevenwindMa/p/3483823.html

哲学家就餐问题-中断解决相关推荐

  1. 哲学家就餐问题python解决_关于哲学家就餐问题的分析代码.

    ①总体思路: 都去拿左边的筷子,并且最后一个人不能去拿筷子(防止大家都拿了左边的筷子,没有右边的筷子,导致死锁了),解决死锁问题的办法就是同时只允许四位哲学家同时拿起同一边的筷子,这样就能保证一定会有 ...

  2. Java多线程学习四十二:有哪些解决死锁问题的策略和哲学家就餐问题

    线上发生死锁应该怎么办 如果线上环境发生了死锁,那么其实不良后果就已经造成了,修复死锁的最好时机在于"防患于未然",而不是事后补救.就好比发生火灾时,一旦着了大火,想要不造成损失去 ...

  3. 用信号量实现进程互斥示例和解决哲学家就餐问题

    用信号量实现进程互斥示例和解决哲学家就餐问题 参考文章: (1)用信号量实现进程互斥示例和解决哲学家就餐问题 (2)https://www.cnblogs.com/alantu2018/p/84731 ...

  4. python解决哲学家就餐问题(and型信号量)

    最近操作系统刚学完这部分内容,老师要求下去自己实践一下,在网上看了看发现用python解决该问题的博文很少,而且好多都是错的,于是就自己写了一段代码 # and型信号量解决哲学家就餐问题 import ...

  5. 哲学家就餐问题python伪代码_GitHub - doooooit/Dining-philosophers-problem: 哲学家进餐问题的两种解决方法...

    哲学家就餐问题 问题描述 哲学家就餐问题(Dining philosophers problem)可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考.吃东西的时候, ...

  6. Thinking in Java---从哲学家就餐问题看死锁现象

    我们知道一个对象可以有synchronized方法或其他形式的加锁机制来防止别的线程在互斥还没释放的时候就访问这个对象.而且我们知道线程是会变成阻塞状态的(挂起),所以有时候就会发生死锁的情况:某个任 ...

  7. 哲学家就餐问题实验报告

    哲学家就餐问题 两个地方应该是pv操作,pv都是操作元语,不可中断 p操作是将信号量-1 v操作是将信号量+1 pv一定要配对使用 哲学家进餐可以通过信号量机制解决,避免死锁 注释如下: test(i ...

  8. Java基础学习之并发篇:哲学家就餐问题

    学习目标 哲学家就餐问题是在计算机科学中的一个经典问题,用来演示在并行计算中多线程同步时产生的问题.在1971年,著名的计算机科学家艾兹格·迪科斯彻提出了一个同步问题,即假设有五台计算机都试图访问五份 ...

  9. 哲学家就餐问题c语言_哲学家就餐问题的一种Python解决方案

    哲学家就餐问题一直是多线程同步问题的经典案例,本文中展示了多线程竞争共享资源带来的死锁问题,并介绍了一种简单的解决方案. 哲学家就餐问题 哲学家最擅长的就是思考和吃饭 ,当他们感觉累的时候,就会拿起一 ...

  10. 哲学家就餐问题--信号量和互斥量预防死锁

    哲学家就餐问题可以采取预防死锁的方案,就是使用互斥量和信号量锁定资源. 互斥量: 对资源进行锁定的意思就是说,当一个哲学家使用叉子的时候,他首先要先把叉子锁定,然后,拿起来.这个时候如果别的哲学家也来 ...

最新文章

  1. 干掉Random:这个类已经成为获取随机数的王者
  2. python比较数据库表今天跟前一天数据增量,Python 生产环境Mysql数据库增量备份脚本...
  3. 扎克伯格All in元宇宙,公司更名Meta,「脸」不要了
  4. Mac版 Android Studio Android Sdk 更新方式
  5. Comcast以纯文本泄露客户Wi-Fi登录信息,立即更改密码
  6. 笔记本电脑电源已接通未充电_dell xps15 电源已接通 未充电 维修方法
  7. Python---二分法查找
  8. 升级oracle spu,关于Oracle数据库PSU/SPU/BundlePatch的补丁号变化
  9. LeetCode 481. 神奇字符串(找规律)
  10. 论文浅尝 | 融入知识的弱监督预训练语言模型
  11. 深度技术win11 32位全新专业版系统v2021.07
  12. mac下安装mysql-pyhon_mac下安装MySQL-python模块
  13. Java把表导出成Excel的代码
  14. c语言成绩管理系统的作用,C语言实现班级成绩管理系统
  15. java视频在线播放_Java实现视频网站的视频上传与视频播放功能.doc
  16. 不同计算机的操作码完全相同,单片机课后习题答案
  17. 对大数据 数据挖掘和机器学习的认识和理解
  18. 插件框架篇一之scrollbars
  19. [Rootkit] dll 隐藏 - VAD
  20. Visio画出简单的拓扑图

热门文章

  1. java实现公式解析
  2. win10怎样取消电脑自动锁屏
  3. RecyclerView多条目加载
  4. 美国国税局将允许纳税人通过现场面试选择退出 ID.me 面部识别
  5. Overleaf 硕士毕业论文参考文献格式设置
  6. 上拉电阻和下拉电阻作用、区别及应用 (转)
  7. oracle 数据库日志归档,ORACLE 数据库日志归档的清理
  8. 美国计算机专业研究生学制几年,美国硕士学制:美国硕士读几年毕业
  9. c语言回调函数的使用及实际作用详解
  10. Mac系统内存越来越大?Mac内存清理技巧