哲学家就餐问题

来源:互联网 发布:js重写confirm样式 编辑:程序博客网 时间:2024/04/29 22:11

哲学家进餐问题:

  • 在什么情况下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 0
原创粉丝点击