linux c語言 哲學家進餐—信號量PV方法一

1、實驗原理

  由Dijkstra提出並解決的哲學家進餐問題(The Dinning Philosophers Problem)是典型的同步問題。該問題是描述有五個哲學家共用一張圓桌,分別坐在周圍的五張椅子上,在圓桌上有五個碗和五隻筷子,他們的生活方式是交替地進行思考和進餐。平時,一個哲學家進行思考,飢餓時便試圖取用其左右最靠近他的筷子,只有在他拿到兩隻筷子時才能進餐。進餐完畢,放下筷子繼續思考。

2.實驗內容:

        顯示出每個哲學家的工作狀態,如吃飯,思考。連續運行30次以上都未出現死鎖現象。

3.分析解決方案一:

現在引入問題的關鍵:這些哲學家很窮,只買得起五根筷子。他們坐成一圈,兩個人的中間放一根筷子。哲學家吃飯的時候必須同時得到左手邊和右手邊的筷子。如果他身邊的任何一位正在使用筷子,那他只有等着。所以我們就假設最多只有4民哲學家在進餐這樣就能保證沒有死鎖的情況。

代碼如下:

 

 

 1 #include<unistd.h> 
 2 #define NUM 5
 3 int ID[NUM]={0,1,2,3,4};
 4 sem_t sem_chopsticks[NUM];
 5 sem_t sem_eaters;
 6 int eaters_num=0;//記錄已經吃過飯的次數 
 7 
 8 //初始化信號量函數 
 9 void sem_signal_init(){
10     int i;
11     for(i=0;i<NUM;i++){
12         if(sem_init(&sem_chopsticks[i],0,1)==-1){
13             perror("oops:em_init error!");
14             exit(1);
15         }
16     }
17     if(sem_init(&sem_eaters,0,NUM-1)==-1){
18             perror("oops:em_init error!");
19             exit(1);
20     }
21     
22     
23 }
24 
25 
26 
27 //執行函數,每個線程相當於一個哲學家 來進行 
28 void * philosopher(void *ptid){
29     int pthread_id=*(int *)ptid%NUM;
30     printf("%d philosopher is thinking...\n",(int)pthread_id);
31     sem_wait(&sem_eaters);
32     //申請左筷子 
33     sem_wait(&sem_chopsticks[pthread_id]); 
34     printf("%d philosopher takes chopstick %d...\n",(int)pthread_id,(int)pthread_id);
35     //申請右筷子
36     sem_wait(&sem_chopsticks[(pthread_id+1)%NUM]);
37     printf("%d philosopher takes chopstick %d...\n",(int)pthread_id,((int)pthread_id+1)%NUM);
38     printf("%d philosopher is eating, %d philosopher had already dined.\n",(int)pthread_id,eaters_num);
39     sem_post(&sem_chopsticks[(pthread_id+1)%NUM]) ;
40     sem_post(&sem_chopsticks[pthread_id]);
41     sem_post(&sem_eaters);
42     eaters_num++;//吃過一次的人加加 
43     printf("%d philosopher had dined, by now %d philosopher had already dined.\n",(int)pthread_id,eaters_num);
44 
45 }
46 
47 
48 
49 
50 int main(int argc,char *argv[]){
51     int i,l,j,k;
52     //循環五個線程多少次 
53     for(l=0;l<1;++l){
54         printf("*******%d times try *******",l+1);
55         pthread_t philosopher_threads[NUM];
56         sem_signal_init();
57         //循環創建五個線程並執行 
58         for(i=0;i<NUM;i++){
59         
60         printf("%d times\n",i);
61         if(pthread_create(&philosopher_threads[i],NULL,philosopher,&ID[i])!=0){
62          perror("oops:pthread_create error!");
63         exit(1);
64             
65         }
66     
67     
68     }
69     
70     //父線程等待子線程都結束才繼續執行 
71     for(j=0;j<NUM;j++){
72         pthread_join(philosopher_threads[j],NULL);
73     }
74     //結束銷毀信號量 
75     sem_destroy(&sem_eaters);
76     for(k=0;k<NUM;++k){
77         sem_destroy(&sem_chopsticks[k]);
78     }
79     eaters_num=0;
80     sleep(2);
81     
82     
83     }
84     
85     
86     
87     return 0;
88 } 

 

運行結果如下:

1 philosopher is thinking...
0 philosopher takes chopstick 0...
3 times
1 philosopher takes chopstick 1...
2 philosopher is thinking...
4 times
1 philosopher takes chopstick 2...
1 philosopher is eating, 0 philosopher had already dined.
3 philosopher is thinking...
4 philosopher is thinking...
1 philosopher had dined, by now 1 philosopher had already dined.
2 philosopher takes chopstick 2...
0 philosopher takes chopstick 1...
0 philosopher is eating, 1 philosopher had already dined.
4 philosopher takes chopstick 4...
3 philosopher takes chopstick 3...
0 philosopher had dined, by now 2 philosopher had already dined.
4 philosopher takes chopstick 0...
4 philosopher is eating, 2 philosopher had already dined.
4 philosopher had dined, by now 3 philosopher had already dined.
3 philosopher takes chopstick 4...
3 philosopher is eating, 3 philosopher had already dined.
3 philosopher had dined, by now 4 philosopher had already dined.
2 philosopher takes chopstick 3...
2 philosopher is eating, 4 philosopher had already dined.
2 philosopher had dined, by now 5 philosopher had already dined.

--------------------------------
Process exited after 2.127 seconds with return value 0
請按任意鍵繼續. . .

後續方案將繼續更新請關注!!!