热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

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

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

 

图1

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

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

定时器(Timer)代码:

  1 #include 
  2 #include 
  3 #include  
  4 #include //为了使用sleep()函数
  5 #include 
  6 #include //为了产生中断
  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)
 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)
 72     {
 73         myfork[k].i = 1;
 74     }
 75     
 76     int i;
 77     //创建和哲学家数量想对应的进程,并且每个进程开始进行吃饭的活动
 78     for( i = 0; 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 )
 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 //每个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)
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)
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 
  2 #include 
  3 #include  
  4 #include //为了使用sleep()函数
  5 #include 
  6 #include //为了产生中断
  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)
 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)
 72     {
 73         myfork[k].i = 1;
 74     }
 75     
 76     int i;
 77     //创建和哲学家数量想对应的进程,并且每个进程开始进行吃饭的活动
 78     for( i = 0; 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 )
 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 //每个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)
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)
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:

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


推荐阅读
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
author-avatar
snailslowdx_619
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有