• 操作系统第六次试验:使用信号量解决进程互斥访问


    姓名:张越

    学号:201821121006

    班级:计算1811

    一:选择的问题:

    哲学家就餐问题

    关于问题的描述:

    五个哲学家围在一个圆桌就餐,每个人都在思考结束以后进行就餐,但是每个人都必须拿起左右两边的两根筷子才能用餐,当每个人都先拿起左筷子,等待右筷子的时候就会造成死锁。

    二:给出伪代码:

    思考结束的哲学家饥饿的等待筷子,接着先拿起左边的筷子,再拿起右边的筷子进行进餐。用餐结束以后释放左右筷子,继续进行思考

    semaphore mutex=1;//互斥地取筷子
    semaphore chopstick[5]={1,1,1,1,1}
    while(true){      
    think();    
    wait(chopstick[i]);   //哲学家拿起左边的筷子
    wait(chopstick[(i+1)mod 5]);    //哲学家拿起右边的筷子
    signal(mutex);     //为了避免同时拿起左边的筷子造成死锁
    eat();    
    signal(chopstick[(i+1)mod 5]);    //释放右边的筷子
    signal(chopstick[i]);      //释放左边的筷子
    think();  //接着进行思考 }}
    

      

    三:给出全部代码

    #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
    ", no);
            sleep(DELAY);
            printf("哲学家%d is hungry
    ", no);
            wait_for_2fork(no);   //拿起一个叉子,等待另外一个 
            printf("哲学家%d is eating
    ", 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;
    }
    

    四;运行结果部分截图:

    程序一直在运行,说明并没有造成死锁

    五:结果分析:

    哲学家就餐图:

    在一开始的时候,所有的哲学家都是在思考状态,接着2号饿了,2号哲学家进行就餐。接着1号3号4号都等待就餐,但是因为2号哲学家正在使用1,2号筷子,所以哲学家1号跟3号缺乏左边的筷子没有办法就餐,就处于等待状态,4号哲学家开始就餐。等到2号哲学家就餐结束释放资源(筷子),1号哲学家就开始就餐。以此类推。

    由此可以看出,位置相邻的哲学家不能同时进餐。

  • 相关阅读:
    组件ListWidget 继承StatefulWidget后动态传入List数据,组件并不会重新渲染。
    Spring Security 采用httpBasic模式认证
    基于Vue2.0实现OpenLayers MarkerCluster海量聚合点标记
    Spring Security 采用formLogin模式认证
    配置页面兼容360浏览器
    如何进行企业工作流选型
    IT项目管理的六种错误思维
    时间管理10项技巧
    一个项目涉及到的50个Sql语句(下)
    SQL Server2000存储过程调试
  • 原文地址:https://www.cnblogs.com/hltz/p/12989791.html
Copyright © 2020-2023  润新知