日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

哲学家进餐问题解析

發布時間:2024/4/17 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 哲学家进餐问题解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這篇文章將給出POSIX的pthread實現,c++11的thread庫的實現方式。部分源碼內容可能摘抄自他人博客,表示此篇文章非絕對原創,感謝。

?

1. 問題描述

場景:5個哲學家,5把叉子,5盤意大利面(意大利面很滑,需要兩把叉子才能拿起)大家圍繞桌子,進行思考與進食的活到,如下圖所示。

哲學家的活動方式為:要么放下左右手刀叉進行思考,要么拿起刀叉開始吃飯(刀叉拿起時,必須拿兩把,而且只能左右手依次拿,先左手拿左邊,后右手拿右邊,或者先右手拿右邊,左邊拿左邊)。其只有這兩種交替狀態。

哲學家們面臨的問題為:如何安排哲學家們一致的行動邏輯,保證他們至少有人且盡可能兩個人能同時拿到兩把叉子開始吃飯,而不會發生“死鎖”,“饑餓”,“干等”的狀態。需要注意的是,大家想吃飯的時機是隨機的,想思考的時機也是隨機的,這個不受控制,不可能由“你”來安排哲學家們哪幾個先吃,哪幾個后吃,他們不受你控制,但你要賦予他們一種性格,或者說思考方式,保證他們自主的思考,自主的解決問題。

  • 死鎖:大家都同時想吃飯,結果同時拿起左手邊叉子,發現同時右邊沒有叉子,然后各懷私心,僵持者希望有人能放下他左手邊叉子,然后搶奪之,開始吃意大利面,結果大家都沒放。。。
  • 饑餓:大家都同時想吃飯,結果同時拿起左手邊叉子,發現同時右邊沒有叉子,然后都很慷慨,結果大家同時放下左手邊叉子,然后大家發現有叉子了,又同時開始拿起左手邊叉子,又同時放下,如此反復。。。
  • 干等:假設想拿叉子這個想法的產生是一個“原子”操作,即不可同時發生,不可中斷,然后一旦有人想拿,就進化為X教授,然后用能力控制了其他人處于僵化狀態,然后開始獨享,獨享完后放下叉子想思考了,立即喪失超能力,于是其余四人回歸正常,然后5人中再次有人想拿叉子,進化為教授,周而復始。但是這樣,尼瑪一個人吃,其余四個干看著啊。。怎么說也有5把叉子,5盤意大利面,至多可以兩個人同時吃的。

?

2. 解決方法

1)服務生解法

2)資源分級解法

3)Chandy/Misra解法

  

3.Posix的pthread實現

pthreadc()為主函數。

1 #include <stdio.h> 2 #include <semaphore.h> 3 #include <pthread.h> 4 #include <unistd.h> 5 6 //宏定義信號量個數為5,宏定義0表示思考,宏定義1表示餓,宏定義2表示吃,宏定義(ph_num+4)%N表示左,宏定義(ph_num+1)%N表示右 7 #define N 5 8 #define THINKING 0 9 #define HUNGRY 1 10 #define EATING 2 11 #define LEFT (ph_num+4)%N 12 #define RIGHT (ph_num+1)%N 13 14 //聲明操作函數,取叉函數,放叉函數,測試函數 15 void* philospher(void *num); 16 void takeFork(int); 17 void putFork(int); 18 void test(int); 19 int pthreadc(); 20 21 //聲明互斥鎖 ,聲明數組 22 sem_t mutex; 23 sem_t S[N]; 24 25 int state[N];//定義整型數組 26 int phil_num[N] = { 0, 1, 2, 3, 4 };//初始化數組 27 28 int pthreadc() 29 { 30 int i; 31 pthread_t thread_id[N];//聲明線程ID數組 32 sem_init(&mutex, 0, 1);//初使化信號量的狀態為1,并且信號量在一個進程的線程間進行共享 33 34 for (i = 0; i<N; i++)//初始化s數組 35 sem_init(&S[i], 0, 0);//初始化S[i]的值為零 36 37 for (i = 0; i<N; i++) 38 { 39 pthread_create(&thread_id[i], NULL, philospher, &phil_num[i]);//創建哲學家線程函數 40 printf("Philosopher %d is ready to grab folks\n", i + 1); 41 } 42 43 for (i = 0; i<N; i++) 44 pthread_join(thread_id[i], NULL);//等待thread_id[i]線程結束 45 } 46 47 48 void* philospher(void *num) 49 { 50 while (1) 51 { 52 int *i = (int*)num; 53 sleep(1);//調整頻率 54 takeFork(*i);//申請叉子 55 sleep(0);//放棄當前線程執行的時間片,把自身放到等待隊列之中。 56 putFork(*i);//放下叉子 57 } 58 59 return nullptr; 60 } 61 62 63 void takeFork(int ph_num) 64 { 65 sem_wait(&mutex);//給信號量的值減上一個“1” 66 state[ph_num] = HUNGRY;//初始化狀態為HUNGRY(餓) 67 printf("Philosopher %d want to eat\n", ph_num + 1); 68 test(ph_num);//測試函數 69 sem_post(&mutex);//給信號量的值加上一個“1” 70 sem_wait(&S[ph_num]);//給信號量的值減上一個“1” 71 sleep(1);//調整頻率 72 } 73 74 75 //******************能夠吃就改變信號量的值和狀態********************************************** 76 void test(int ph_num) 77 { /*如果state[ph_num]狀態為HUNGRY并且state[LEFT]和state[RIGHT]的狀態都不等于EATING*/ 78 if (state[ph_num] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) 79 { 80 state[ph_num] = EATING;//將state[ph_num]狀態置為EATING(吃飯) 81 sleep(2);//調整頻率 82 printf("Philosopher %d is eating now\n", ph_num + 1); 83 sem_post(&S[ph_num]);//給信號量的值加上一個“1” 84 } 85 } 86 87 88 //****************************************************************************************** 89 void putFork(int ph_num) 90 { 91 sem_wait(&mutex);//信號量減1 92 state[ph_num] = THINKING;//將state[ph_num]狀態置為THINKING(思考) 93 printf("Philosopher %d is thinking now\n", ph_num + 1); 94 test(LEFT); 95 test(RIGHT); 96 sem_post(&mutex);//給信號量的值加上一個“1” 97 }

?

?

  

?

轉載于:https://www.cnblogs.com/pan89/p/3772671.html

總結

以上是生活随笔為你收集整理的哲学家进餐问题解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。