姓名:李瑶

学号:201821121002

班级:计算1811

1. 哲学家进餐问题

有五个哲学家,他们的生活方式是交替地进行思考和进餐。他们共用一张圆桌,分别坐在五张椅子上。

在圆桌上有五个碗和五支筷子,平时一个哲学家进行思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕,放下筷子又继续思考。

2. 给出伪代码  

    5位哲学家与左右邻居对其中间筷子的访问时互斥关系,但与之前遇到的问题不同的是,每个哲学家进程需要同时持有两个临界资源才能开始吃饭,因此要避免临界资源分配不当造成的死锁现象。

    通过互斥信号量mutex对eat()之前取左侧和右侧筷子的操作进行保护,可以防止死锁的出现。

semaphore mutex=1;//互斥地取筷子

semaphore chopstick[5]={1,1,1,1,1}

void philosopher (int i){ //i号哲学家的进程

   while(true){

      think();

    wait(cjopstick[i]);

    wait(chopstick[(i+1)mod 5]);

    signal(mutex);

    eat();

    signal(chopstick[(i+1)mod 5]);

    signal(chopstick[i]);

       think();

   }

}

3. 给出完整代码

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/wait.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

union semun
{
    int val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO (Linux-specific) */
};

int semid;

#define DELAY (rand() % 5 + 1)

void wait_for_2fork(int no)
{
    int left = no;
    int right = (no + 1) % 5;

    struct sembuf buf[2] =
    {
        {left, -1, 0},
        {right, -1, 0}
    };

    semop(semid, buf, 2);
}

void free_2fork(int no)
{
    int left = no;
    int right = (no + 1) % 5;

    struct sembuf buf[2] =
    {
        {left, 1, 0},
        {right, 1, 0}
    };

    semop(semid, buf, 2);
}

void philosopere(int no)
{
    srand(getpid());
    for (; ;)
    {

        printf("%d is thinking\n", no);
        sleep(DELAY);
        printf("%d is hungry\n", no);
        wait_for_2fork(no);
        printf("%d is eating\n", no);
        sleep(DELAY);
        free_2fork(no);
    }
}


int main(void)
{

    semid = semget(IPC_PRIVATE, 5, IPC_CREAT | 0666);
    if (semid == -1)
        ERR_EXIT("semget");
    union semun su;
    su.val = 1;
    int i;
    for (i = 0; i < 5; i++)
    {
        semctl(semid, i, SETVAL, su);
    }

    int no = 0;
    pid_t pid;
    for (i = 1; i < 5; i++)
    {
        pid = fork();
        if (pid == -1)
            ERR_EXIT("fork");

        if (pid == 0)
        {
            no = i;
            break;
        }
    }

    philosopere(no);

    return 0;
}

 

4. 运行结果并解释

 

 

 结果解释:

首先哲学家0~4先进行思考,当饿了的时候就需要就餐,若能同时拿到自己左右两边的叉子则可以开始就餐,否则就需要继续等待。从结果中可以看出五个哲学家最多只能有两个同时就餐,且位置不能相邻;因为结果执行一直没有停止,说明没有发生死锁现象。

posted on 2020-05-29 16:36  霓袅  阅读(199)  评论(0编辑  收藏  举报