哲学家进餐问题

哲学家进餐问题

  • 问题描述
    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');



}
                                          
                                                                               
  • 运行结果
    在这里插入图片描述
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值