哲学家就餐问题:五个哲学家五根筷子,如果哪个科学家饿了,则先拿起左边的筷子,再拿起右边的侉子,但是只有同时拥有左右筷子即可进食,因此如果出现极端的情况:五个哲学家都饿了,那么他们同时拿起自己的左筷子,那么他们都没有右筷子,这时谁都不愿意放弃自己的左筷子,这就导致谁都吃不到东西,这就导致了死锁。
解决这一问题的方法是:每根筷子设置为信号量,左右2根筷子要么不分配,要么都给,即用信号量将其控制起来,这样保证肯定有人同时拥有左、右2只筷子,并且用完马上释放,这就避免了死锁。
代码:
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <sys/ipc.h>
5 #include <sys/sem.h>
6
7 //用来给信号量设置初值的联合体
8 union semun
9 {
10 int value;
11 };
12 int id;//信号量集在几个函数都用到,设置为全局的
13
14 //哲学家获取2只筷子
15 void getchop(int num)
16 {
17 //直接初始化2个信号量
18 struct sembuf sb[2]={
19 {num,-1,0},
20 {(num+1)%5,-1,0}
21 };
22 semop(id,sb,2);//对id这个信号量集中的2个信号量按照结构体sb进行操作
23 }
24 //哲学家放下2只筷子(即进行V操作)
25 void putchop(int num)
26 {
27 //直接初始化2个信号量
28 struct sembuf sb[2]={
29 {num,1,0},
30 {(num+1)%5,1,0}
31 };
32 semop(id,sb,2);//对id这个信号量集中的2个信号量按照结构体sb进行操作
33 }
34 //每个哲学家的日常活动
35 void fun(int num)
36 {
37 while(1)
38 {
39 printf("%d号哲学家开始思考\n",num);
40 sleep(rand()%5);
41 getchop(num);//哲学家获得2只筷子
42 printf("2只筷子已得到,%d号哲学家开始大吃\n",num);
43 sleep(rand()%5);
44 printf("%d号哲学家吃饱了\n");
45 putchop(num);//哲学家放下2只筷子
46 }
47 }
48 int main()
49 {
50 //创建拥有5个信号量的信号量集
51 id=semget(1234,5,IPC_CREAT|0644);
52 int num=0;
53 //循环给每个信号量设置初值为1
54 union semun su={1};
55 int i=0;
56 int j=1;
57 for(i=0;i<5;i++)
58 {
59 semctl(id,i,SETVAL,su);
60 }
61
62 //再创建4个子进程,加上一个父进程,一共5个进程,相当于五个哲学家
63 for(j=1;j<5;j++)
64 {
65 pid_t pid=fork();
66 if(pid==0)
67 {
68 num=j;//使得1,2,3,4 代表四个子进程
69 break;
70 }
71 }
72
73 fun(num);//用每个子进程(哲学家)进行自己的活动
74
75 return 0;
76 }