哲学家进餐问题
程序员文章站
2022-07-12 20:58:37
...
哲学家进餐问题
- 问题描述
1、五位哲学家围坐在一张圆形桌子上,桌子上有一盘饺子。每一位哲学家要么思考,要么等待,要么吃饺子。为了吃饺子,哲学家必须拿起两只筷子,但是每个哲学家旁边只有一只筷子,也就是筷子数量和哲学家数量相等,所以每只筷子必须由两个哲学家共享。设计一个算法以允许哲学家吃饭。
2、算法必须保证互斥(没有两位哲学家同时使用同一只筷子)
3、同时还要避免死锁(每人拿着一只筷子不放,导致谁也吃不了)
4、限制同时吃饭的哲学家数,下面例子中同时只允许4个哲学家同时吃饭;或者通过给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则首先拿右边的筷子来避免死锁。 - 代码示例
/philosopher_eat.c
//
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sem.h>
#include<error.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/wait.h>
int roomnum; //房间数量,通过房间数量来限制同一时间进餐的哲学家数量
int chopsticks[5]; //五根筷子
//定义P操作
int waitsem(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id,&sem_b,1)==-1){
fprintf(stderr, "wait failed!");
return 0;
}
return 1;
}
//定义V操作
int signalsem(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id,&sem_b,1)==-1){
fprintf(stderr,"signal failed!");
return 0;
}
return 1;
}
int main(int argc, char argv[])
{
pid_t pid;
pid_t pids[5];
int i = 0;
char ch; //用于控制算法结束
//信号量的初始化
roomnum = semget(IPC_PRIVATE,1,0666|IPC_CREAT);
semctl(roomnum,0,SETVAL,4);
for(i=0;i<5;i++)
{
chopsticks[i]=semget(IPC_PRIVATE,1,0666|IPC_CREAT);
semctl(chopsticks[i],0,SETVAL,1);
}
//创建进程
for(i=0;i<5;i++)
{
pid = fork();
if( pid<0 ){
fprintf(stderr,"fork philosopher failed!\n");
exit(-1);
}
if( pid==0 )
{
while(1){
//哲学家在思考
printf("philosopher %d is thinking. no disterb\n", i);
sleep(1);
//哲学家感到饿了,进房间
waitsem(roomnum);
printf("philosopher %d is hungry. so he entered the room\n",i);
//哲学家拿起左筷子
waitsem(chopsticks[i]);
printf("philosopher %d pick up left chopstick\n",i);
//哲学家拿起右筷子
waitsem(chopsticks[(i+1)%5]);
printf("philosopher %d pick up right chopstick\n",i);
//拿到两根筷子的哲学家开始吃饭
printf("philosopher %d begin to eat\n",i);
sleep(5-i);
//哲学家吃完饭
printf("philosopher %d end to eat\n",i);
//哲学家放下右筷子
signalsem(chopsticks[(i+1)%5]);
printf("philosopher %d put down right chopstick\n",i);
//哲学家放下左筷子
signalsem(chopsticks[i]);
printf("philosopher %d put down left chopstick\n",i);
//哲学家离开房间
signalsem(roomnum);
printf("philosopher %d left the room\n",i);
printf("philosopher %d begin to think\n",i);
sleep(1);
}
}else{
pids[i]=pid;
}
}
do{
ch=getchar();
if(ch=='q')
for(i=0;i<5;i++)
kill(pids[i],SIGTERM);
}while(ch!='q');
}
- 运行结果
下一篇: Nginx#Nginx反向代理