哲学家就餐问题

哲学家进餐问题:

  • 在什么情况下5 个哲学家全部吃不上饭?
    假如所有的哲学家都同时拿起左侧筷子,看到右侧筷子不可用,又都放下左侧筷子,
    等一会儿,又同时拿起左侧筷子,如此这般,永远重复。对于这种情况,即所有的程序都在
    无限期地运行,但是都无法取得任何进展,即出现饥饿,所有哲学家都吃不上饭。
  • 这里给出一种避免死锁的解决方式。

    最多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释
    放出他所使用过的两支筷子,从而可使更多的哲学家进餐。

    以下将room 作为信号量,只允 许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入
    餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会 出现饿死和死锁的现象。

  • 下面给出详细的 C代码实现。

头文件

    #pragma once 
    #include <stdio.h>
    #include <tchar.h>
    #include <process.h>
    #include <stdlib.h>
    #include <Windows.h>
    #include <time.h>
    #include <math.h>
    #include <GLAUX.H>
    #include <gl/GL.h>
    #include <gl/GLU.h>
    #include <gl/glut.h>
    #include <SDKDDKVer.h>

主程序代码

    #include "stdafx.h"
    HANDLE chopstick[5],room;
    LPCRITICAL_SECTION cs;
    const GLfloat Pi = 3.1415926536f;
    const GLfloat R = 10.0f;
    //五个中心的坐标
    const GLfloat x[5] = { 200, 105, 141, 259, 295 };
    const GLfloat y[5] = { 300, 231, 119, 119, 231 };
    //代表5个哲学家的状态,0表示思考,1表示吃饭,2表示等待
    int state[5] = { 0, 0, 0, 0, 0 };

    void initchopstick(){
        for (int i = 0; i < 5; i++){
            chopstick[i] = CreateSemaphore(NULL, 1, 1, TEXT("chopstick"+i));
        }
        room = CreateSemaphore(NULL, 4, 4, TEXT("room"));
    }

    int srandNum(){
        srand(time(0));
        return (rand() % 100);
    }

    void think(int i){
        printf("哲学家%d正在思考\n", i);
        state[i] = 0;
        Sleep((DWORD(srandNum() % 10000+2000)));
    }

    void eat(int i){
        printf("哲学家%d正在吃饭\n", i);
        state[i] = 1;
        Sleep((DWORD(srandNum() % 10000+2000)));
    }

    void philosopher(PVOID p)
    {
        int i = (int)p;
        while (true)
        {
            think(i);
            //等待状态
            state[i] = 2;
            WaitForSingleObject(room, INFINITE);
            WaitForSingleObject(chopstick[i], INFINITE);//请求左手边的筷子
            WaitForSingleObject(chopstick[(i + 1) % 5], INFINITE);//请求右手边的筷子 
            EnterCriticalSection(cs);
            eat(i);
            LeaveCriticalSection(cs);
            Sleep(500);
            ReleaseSemaphore(chopstick[(i + 1) % 5],1,NULL); //释放右手边的筷子 
            ReleaseSemaphore(chopstick[i],1,NULL); //释放左手边的筷子 
            ReleaseSemaphore(room,1,NULL); //退出房间释放信号量room 
        }
    }

    // 函数RenderScene用于在窗口中绘制需要的图形
    void RenderScene(void)
    {
        //用当前清除色清除颜色缓冲区,即设定窗口的背景色
        glClear(GL_COLOR_BUFFER_BIT);
        for (int i = 0; i < 5; i++){
            //设置当前绘图使用的RGB颜色
            if (state[i] == 2){
                glColor3f(1.0f, 1.0f, 0.0f);//黄色代表等待
            }
            else if (state[i] == 1){
                glColor3f(0.0f, 1.0f, 0.0f);//绿色代表吃饭
            }
            else if (state[i] == 0){
                glColor3f(1.0f, 0.0f, 0.0f);
            }
            glRectf(x[i] - R, y[i] - R, x[i] + R, y[i] + R);
        }
        //清空命令缓冲区并交换帧缓存
        glutSwapBuffers();
    }

    // 函数ChangeSize是窗口大小改变时调用的登记函数
    void ChangeSize(GLsizei w, GLsizei h)
    {
        if (h == 0)     h = 1;
        //设置视区尺寸
        glViewport(0, 0, w, h);

        // 重置坐标系统,使投影变换复位
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        // 建立修剪空间的范围
        if (w <= h)
            glOrtho(0.0f, 400.0f, 0.0f, 400.0f*h / w, 1.0f, -1.0f);
        else
            glOrtho(0.0f, 400.0f*w / h, 0.0f, 400.0f, 1.0f, -1.0f);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }

    void TimerFunction(int value)
    {
        glutPostRedisplay();
        glutTimerFunc(33, TimerFunction, 1);
    }

    void SetupRC(void)
    {
        //设置窗口清除色为蓝色
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        initchopstick();
        cs = (LPCRITICAL_SECTION)malloc(sizeof(LPCRITICAL_SECTION));
        InitializeCriticalSection(cs);
        for (int i = 0; i < 5; i++){
            _beginthread(philosopher, NULL, (PVOID)i);
        }
        glutInitDisplayMode(GLUT_RGB |GLUT_DOUBLE);
        glutInitWindowSize(800, 800);
        glutCreateWindow("Draw");
        glutDisplayFunc(RenderScene);
        glutReshapeFunc(ChangeSize);
        glutTimerFunc(33, TimerFunction, 1);
        SetupRC();
        glutMainLoop();
        Sleep(INFINITE);
        DeleteCriticalSection(cs);
        return 0;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值