哲学家用餐模型分析

来源:互联网 发布:虹越400官网和淘宝店 编辑:程序博客网 时间:2024/04/28 22:22

#include #include #include #include pthread_mutex_t m[5];void *tfn(void *arg){int i, l, r;srand(time(NULL));i = (int)arg;if (i == 4)l = 0, r = i;elsel = i; r = i+1;while (1) {pthread_mutex_lock(&m[l]);if (pthread_mutex_trylock(&m[r]) == 0) {printf("\t%c is eating \n", 'A'+i);pthread_mutex_unlock(&m[r]);}pthread_mutex_unlock(&m[l]);sleep(rand() % 5);}return NULL;}int main(void){int i;pthread_t tid[5];for (i = 0; i < 5; i++)pthread_mutex_init(&m[i], NULL);for (i = 0; i < 5; i++)pthread_create(&tid[i], NULL, tfn, (void *)i);for (i = 0; i < 5; i++)pthread_join(tid[i], NULL);for (i = 0; i < 5; i++)pthread_mutex_destroy(&m[i]);return 0;}
多线程版:

         选用互斥锁mutex,如创建5个, pthread_mutex_t m[5];

         模型抽象:    

                   5个哲学家 --> 5个线程;    5支筷子 --> 5把互斥锁                  int left(左手), right(右手)

                   5个哲学家使用相同的逻辑,可通用一个线程主函数,void *tfn(void *arg),使用参数来表示线程编号:int i = (int)arg;

                   哲学家线程根据编号知道自己是第几个哲学家,而后选定锁,锁住,吃饭。否则哲学家thinking。

                                                                                A  B   C   D   E

                   5支筷子,在逻辑上形成环:0   1  2   3   4   分别对应5个哲学家:


所以有:

                   if(i== 4)   

                            left= i, right = 0;

                   else

                            left= i, right = i+1;

         振荡:如果每个人都攥着自己左手的锁,尝试去拿右手锁,拿不到则将锁释放。过会儿五个人又同时再攥着左手锁尝试拿右手锁,依然拿不到。如此往复形成另外一种极端死锁的现象——振荡。

         避免振荡现象:只需5个人中,任意一个人,拿锁的方向与其他人相逆即可(如:E,原来:左:4,右:0 现在:左:0, 右:4)。

         所以以上if else语句应改为:

                   if(i== 4)   

                            left= 0, right = i;

                   else

                            left= i, right = i+1;

         而后,首先应让哲学家尝试加左手锁: 

while {

                            pthread_mutex_lock(&m[left]);     如果加锁成功,函数返回再加右手锁,

                                                                                             如果失败,应立即释放左手锁,等待。

                            若,左右手都加锁成功--> 吃 --> 吃完 --> 释放锁(应先释放右手、再释放左手,是加锁顺序的逆序)

                   }

         主线程(main)中,初始化5把锁,销毁5把锁,创建5个线程(并将i传递给线程主函数),回收5个线程。

避免死锁的方法:

         1. 当得不到所有所需资源时,放弃已经获得的资源,等待。

         2. 保证资源的获取顺序,要求每个线程获取资源的顺序一致。如:A获取顺序1、2、3;B顺序应也是1、2、3。若B为3、2、1则易出现死锁现象。                                                                                                      

多进程版

相较于多线程需注意问题:

         需注意如何共享信号量 (注意:坚决不能使用全局变量 sem_t s[5])

实现:

         main函数中:       

循环sem_init(&s[i], 0, 1); 将信号量初值设为1,信号量变为互斥锁。

                   循环 sem_destroy(&s[i]);

                   循环创建 5 个子进程。 if(i < 5) 中完成子进程的代码逻辑。

                   循环回收 5 个子进程。

         子进程中:

if(i == 4) 

left = 0, right == 4;

                   else 

left = i, right = i+1;  

                   while(1) {

                            使用sem_wait(&s[left]) 锁左手,尝试锁右手,若成功 --> 吃;若不成功 --> 将左手锁释放。

                            吃完后, 先释放右手锁,再释放左手锁。

                   }

【重点注意】:

直接将sem_t s[5]放在全局位置,试图用于子进程间共享是错误的!应将其定义放置与mmap共享映射区中。main中:

sem_t *s =mmap(NULL, sizeof(sem_t) * 5, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANON, -1, 0);

         使用方式:将s当成数组首地址看待,与使用数组s[5]没有差异。     



#include #include #include #include pthread_mutex_t m[5];void *tfn(void *arg){int i, l, r;srand(time(NULL));i = (int)arg;if (i == 4)l = 0, r = i;elsel = i; r = i+1;while (1) {pthread_mutex_lock(&m[l]);if (pthread_mutex_trylock(&m[r]) == 0) {printf("\t%c is eating \n", 'A'+i);pthread_mutex_unlock(&m[r]);}pthread_mutex_unlock(&m[l]);sleep(rand() % 5);}return NULL;}int main(void){int i;pthread_t tid[5];for (i = 0; i < 5; i++)pthread_mutex_init(&m[i], NULL);for (i = 0; i < 5; i++)pthread_create(&tid[i], NULL, tfn, (void *)i);for (i = 0; i < 5; i++)pthread_join(tid[i], NULL);for (i = 0; i < 5; i++)pthread_mutex_destroy(&m[i]);return 0;}


                                  

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 欧卡二进游戏就卡画面了怎么办 魅族手机的微信图标找不到了怎么办 金立手机:微信图标找不到怎么办? 鞋厂装跟机老是卡钉怎么办 苹果手机摔了一下开不了机怎么办 百度网盘解析的种子保存不了怎么办 下载了种子百度网盘解析不了怎么办 正畸复诊后吃饭一直会磨嘴怎么办 遇到儿子说话对母亲不满母亲怎么办 冰箱旧了怎么办教你创新冰箱翻新法 微信陌生人加好友发红包怎么办 微信红包发了对方收不到怎么办 发红包是微信密码不知道了该怎么办 微信上红包密码不知道密码怎么办 本人不知道微信自动发红包怎么办 微信钱包里的钱没了怎么办 微信聊天删除了红包没领怎么办 微信红包未领取删掉了怎么办 微信红包没领取删掉了怎么办 微信红包没领取就删除好友了怎么办 老公一个人出去玩不愿带老婆怎么办 干了一年也攒不下钱怎么办 住院出院后请领导同事吃饭怎么办 有同事请吃饭答应了又不想去怎么办 同事请吃饭发红包不收怎么办 同事要走了请吃饭我不想去怎么办 请领导吃饭他说今晚有事我该怎么办 两个月的狗狗不吃狗粮怎么办 挖机驾驶室的小镙杆总是掉该怎么办 开挖机出了事故没有证怎么办 发现小孩有早恋现象做家长该怎么办 马上中考了初三孩子不上学怎么办 初三孩子老说自己难受不上学怎么办 幼儿园安全教案迷路了怎么办及反思 老婆发现我出轨后离家出走了怎么办 把丝袜放进马桶水箱堵了怎么办 如果老公那方面不行但人很好怎么办 老公哪里都好就是那方面不行怎么办 电饭锅盖子卡的地方掉了怎么办 唯品会退货已经收到了不退款怎么办 有人用qq冒充我和别人聊天怎么办