实验题目:同步机制——信号量集与哲学家就餐问题
实验目的:理解Linux系统中基于信号量集的同步机制,并使用该同步机制解决并发进程的同步问题。
实验内容:1.定义5把叉子的信号量集。
2.编写5个哲学家的就餐活动,解决哲学家就餐时对叉子资源的申请和释放。
3.用fork()系统调用创建5个哲学家进程并使其并发执行,通过观察运行结果判断同步算法的正确性。
实验代码:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
}arg;
int semid;
philosopher(int i)
{
int j;
struct sembuf sbuf[2];
sbuf[0].sem_num=i;
sbuf[0].sem_flg=SEM_UNDO;
sbuf[1].sem_num=(i+1)%5;
sbuf[1].sem_flg=SEM_UNDO;
for(j=0;j<5;j++)
{
printf("philosopher %d is thinking\n",i);
sleep(2);
printf("philosopher %d is hungry\n",i);
sbuf[0].sem_op=-1;
sbuf[1].sem_op=-1;
semop(semid,sbuf,2);
printf("philosopher %d is eating\n",i);
sleep(2);
sbuf[0].sem_op=1;
sbuf[1].sem_op=1;
semop(semid,sbuf,2);
}
exit(i);
}
int main(){
int semid,key,pid,status,i;
key=ftok("fname",1);
semid=semget(key,5,IPC_CREAT|0666);
arg.val=1;
for(i=0;i<5;i++)
semctl(semid,i,SETVAL,arg);
for(i=0;i<5;i++)
{
pid=fork();
if(pid==0)
philosopher(i);
}
pid=wait(&status);
}
(原书代码中的while(1)改为了for(j,1-5)循环并加了一个exit(),否则会一直运行下去)
实验结果:
思考题:
1.解决方案中是否出现饥饿?为什么?
有可能。如果第(i-1)%5号哲学家和第(i+1)%5号哲学家总是至少有一个处于进食状态,则第i号哲学家将会被“饿死”。尽管发生概率较低,但并不能完全排除其可能性。