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...
",(int)pthread_id);
31     sem_wait(&sem_eaters);
32     //申请左筷子 
33     sem_wait(&sem_chopsticks[pthread_id]); 
34     printf("%d philosopher takes chopstick %d...
",(int)pthread_id,(int)pthread_id);
35     //申请右筷子
36     sem_wait(&sem_chopsticks[(pthread_id+1)%NUM]);
37     printf("%d philosopher takes chopstick %d...
",(int)pthread_id,((int)pthread_id+1)%NUM);
38     printf("%d philosopher is eating, %d philosopher had already dined.
",(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.
",(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
",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
请按任意键继续. . .

后续方案将继续更新请关注!!!

原文地址:https://www.cnblogs.com/lhyzdd/p/13989621.html