文章目录

  • 一、开发环境
  • 二、进餐问题
  • 三、系统分析
  • 四、程序流程图
  • 五、源代码
    • 5.1 多线程实现
    • 5.2 C语言模拟

一、开发环境

开发平台: Visual C++6.0
开发环境: Windows XP
开发语言: C语言+API(windows应用程序编程接口)

二、进餐问题

一个圆桌上有一大碗面,5个盘子,5把筷子,5个座位上可以座5个哲学家,当哲学家就坐以后,其左右有且仅有一个筷子,每个筷子左又有且仅有一个哲学家。哲学家动作:思考,取筷(需要两个),取面,吃面。现设计一个礼仪以允许他们就餐,需要避免两个哲学家“抢”同一把筷子,又要避免饥饿和死锁。

三、系统分析

  1. 互斥解决。每一把筷子使用一个2元信号量,只有获得信号量的哲学家才能使用筷子,从而避免对筷子的“抢夺”。
  2. 死锁和饥饿解决。餐厅只允许最多4名哲学家进入,因为总有一个哲学家可以得到两把筷子,从而可以正常就餐,因此不会有死锁出现。每为哲学家就餐完毕后,立即离开,放下筷子,以便没有用餐的哲学家可以使用,这也能保证不会有饥饿的存在了。
  3. 就餐顺序随机。为了较真实地模拟现实就餐问题,哲学家每次进入餐厅的顺序总是随机的,这个随机顺序在哲学家开始进入之间通过一个函数产生(这个过程会花一定时间)。
  4. 哲学家的各种状态。
    位置空闲:当哲学家没有就座的时候,该位置显示空闲状态。
    思考等待:当一个哲学家进入餐厅但是没有获得餐具就餐的时候,进入思考等待状态。
    就餐:哲学家获得餐具后开始就餐进入就餐状态(就餐时间8000ms)。
    离开:哲学家就餐完毕就到了离开状态。
  5. 每个哲学家的就餐过程通过一个线程函数的调用来实现。

四、程序流程图

五、源代码

5.1 多线程实现

代码如下:

// 解决哲学家就餐问题
// 每个哲学家可用一个线程来模拟。
// 设有5个哲学家,5只筷子,每个哲学家吃饭时间为一个随机值,哲学家吃饭后的思考时间也是一个随机值。
#include <Windows.h>
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <time.h>
/*
(1)奇数号的哲学家先拿起右边的筷子再拿起左边的筷子。(2)偶数号哲学家先拿起左边的筷子,再拿起右边的筷子。(3)如果哲学家抢到一只筷子,在抢占另一只筷子时失败,则要放弃已经抢占到的资源。(4)左右两边都抢到筷子的哲学家,吃完放后释放资源。*/
using namespace std;HANDLE chop[5];
HANDLE ph[5];
HANDLE mutex;
int nums = 0;int random()
{return rand() % 100 + 20;
}void eating(int id)
{int num = random();Sleep(num);printf("\t\t\t哲学家%d号吃了%d秒\n", id, num);
}DWORD WINAPI phthread(LPVOID param) {nums++;int id = nums;int lc = id - 1;int rc = id % 5;int times = 0;int ret1, ret2;while (true){Sleep(100);if (times >= 2)break;if (id % 2 == 0){ret1 = WaitForSingleObject(chop[lc], 0);if (ret1 == WAIT_OBJECT_0){ret2 = WaitForSingleObject(chop[rc], 0);if (ret2 == WAIT_OBJECT_0){WaitForSingleObject(mutex, INFINITE);printf("哲学家%d号拿到两只筷子开始吃第%d顿饭。\n", id, times + 1);ReleaseMutex(mutex);times++;WaitForSingleObject(mutex, INFINITE);eating(id);ReleaseMutex(mutex);WaitForSingleObject(mutex, INFINITE);printf("\t\t\t哲学家%d号吃完两顿饭啦,放下筷子。\n", id);ReleaseMutex(mutex);ReleaseSemaphore(chop[rc], 1, NULL);}ReleaseSemaphore(chop[lc], 1, NULL);}}else{ret1 = WaitForSingleObject(chop[rc], 0);if (ret1 == WAIT_OBJECT_0){ret2 = WaitForSingleObject(chop[lc], 0);if (ret2 == WAIT_OBJECT_0){WaitForSingleObject(mutex, INFINITE);printf("哲学家%d号拿到两只筷子开始吃%d顿饭。\n", id, times + 1);ReleaseMutex(mutex);times++;WaitForSingleObject(mutex, INFINITE);eating(id);ReleaseMutex(mutex);WaitForSingleObject(mutex, INFINITE);printf("\t\t\t哲学家%d号吃完两顿饭啦,放下筷子。\n", id);ReleaseMutex(mutex);ReleaseSemaphore(chop[lc], 1, NULL);}ReleaseSemaphore(chop[rc], 1, NULL);}}WaitForSingleObject(mutex, INFINITE);ReleaseMutex(mutex);}printf("=======哲学家%d吃饱了然后离开了。=======\n", id);return 0;
}int main()
{srand((unsigned)time(0));mutex = CreateMutex(NULL, false, NULL);for (int i = 0; i < 5; ++i){chop[i] = CreateSemaphore(NULL, 1, 1, NULL);}for (int i = 0; i < 5; ++i){int j = i + 1;ph[i] = CreateThread(NULL, 0, phthread, NULL, 0, NULL);}Sleep(10000);  // 释放句柄for (int i = 0; i < 5; ++i){CloseHandle(ph[i]);CloseHandle(chop[i]);}CloseHandle(mutex);Sleep(500);system("pause");return 0;
}

运行结果为:

5.2 C语言模拟

代码如下(不太好):

#include<iostream>
#include<stdlib.h>
#include<string>
#include<time.h>
#include<windows.h>using namespace std;int l = 0;
int w = 0;                 //阻塞的进程个数,用来实现最多有四个哲学家同时拿筷子,避免死锁。
int s[5] = { 1,1,1,1,1 };  //筷子的信号量
int come_order[5] = { 0,0,0,0,0 }; // 就餐顺序
int wake[5] = { 0,0,0,0,0 };       // 阻塞唤醒顺序
int *q = wake;
int p(int*);
int v(int*);
int pro(int);//执行
int p(int *i)//p操作
{*i -= 1;if (*i < 0){w++;return 1;}else return 0;
}int v(int *i)
{*i += 1;if (*i <= 0) return 1;else return 0;}void eat(int i)
{cout << "第" << i << "位哲学家正在吃饭。" << endl;Sleep(3000);
}int pro(int i)
{if (p(&s[i - 1])){cout << "第" << i << "位哲学家请等待...." << endl;return 1;}if (p(&s[i])){cout << "第" << i << "位哲学家请等待...." << endl;return 1;}eat(i);if (v(&s[i])) *(q + i) = 1;if (v(&s[i - 1])) *(q + i) = 1;cout << "第" << i << "位哲学家吃饱离开了。" << endl;return 0;
}int get_rand() {//产生1到5之间的整数srand((unsigned)time(NULL));int RANGE_MIN = 1;int RANGE_MAX = 6;int randn = rand() % (RANGE_MAX - RANGE_MIN) + RANGE_MIN;return randn;
}
bool if_num_exist(int num) {for (int a = 0; a < 5; a++) {if (come_order[a] == num)return true;}return false;
}
void get_rand_order()
{//产生随机的进入顺序int temp = 0;bool tmp = 1;for (int a = 0; a < 5; a++){while (tmp){temp = get_rand();if (!if_num_exist(temp)){come_order[a] = get_rand();tmp = 0;}}tmp = 1;}cout << "饥饿顺序:" << come_order[0] << " " << come_order[1] << " " << come_order[2] << " " << come_order[3] << " " << come_order[4] << endl;
}
void get_order()
{int p[5];cout << "请输入五位哲学家的状态:" << endl << "                1表示饥饿,0表示思考。" << endl << "若有两个以上的哲学家同时饥饿,优先考虑小号的。" << endl;cin >> p[0] >> p[1] >> p[2] >> p[3] >> p[4];int a = 0;for (int k = 0; k < 5; k++){if (p[k] == 1) come_order[a++] = k + 1;}
}void main()
{int c;cout << "请选择进餐顺序生成方式,0表示随机生成,1表示手动输入:" << endl;cin >> c;if (c == 0) get_rand_order();else if (c == 1)  get_order();else { cout << "error" << endl; }while (w < 3){for (int a = 0; a < 5; a++) { if (come_order[a] != 0) pro(come_order[a]); }for (int a = 0; a < 5; a++) { if (*(q + a) != 0) pro(*(q + a)); }}
}

运行结果为:

C++实现进程调度模拟程序——哲学家进餐问题相关推荐

  1. 操作系统 实验三 进程调度模拟程序

                                                          实验三 进程调度模拟程序                                   ...

  2. IPC之哲学家进餐问题

    A问题: 1965年,Dijkstra提出并解决了一个他称之为哲学家进餐的同步问题. "五个哲学家围坐在一张圆桌周围,每个哲学家的前面都有一份通心面,由于面条很滑,必须使用2把叉子才能夹住. ...

  3. 实验三进程调度模拟程序

    实验三 进程调度模拟程序 专业:物联网工程   姓名:王鸾  学号:201306104128 一. 实验目的和要求 目的: 用高级语言完成一个进程调度程序,以加深对进程的概念及进程调度算法的理解. 实 ...

  4. 操作系统(四) | 经典进程的同步问题(生产者--消费者问题、哲学家进餐问题、读者--写者问题)

    文章目录 生产者--消费者问题 分析 实现 哲学家进餐问题 方法一:最多4人同时拿左筷子,最终保证一人能进餐 方法二:同时给左右筷子 解法1:AND信号量 解法2:信号量保护机制 方法三:让奇数先左后 ...

  5. 操作系统:哲学家进餐问题

    哲学家进餐问题 五个哲学家围着一张圆桌,每个哲学家面前放着食物.哲学家的生活有两种交替活动:吃饭以及思考.当一个哲学家吃饭时,需要先拿起自己左右两边的两根筷子,并且一次只能拿起一根筷子. 下面是一种错 ...

  6. 2.3.6 操作系统之进程同步与互斥经典问题(生产者-消费者问题、多生产者-多消费者问题、吸烟者问题、读者-写者问题、哲学家进餐问题)

    文章目录 0.前言 1.生产者-消费者问题 (1)问题描述 (2)问题分析 (3)如何实现? (4)实现互斥的P操作一定要在实现同步的P操作之后 (5)知识回顾与重要考点 2.多生产者-多消费者问题 ...

  7. 操作系统:经典进程同步问题 之 生产者-消费者问题、读者-写者问题、哲学家进餐问题

    在进程同步中,经典的同步问题有:生产者-消费者问题.读者-写者问题.哲学家进餐问题. 一.生产者与消费者问题: 问题描述:使用一个缓冲区来保存物品,只有缓冲区没有满,生产者才可以放入物品:只有缓冲区不 ...

  8. 实验三 进程调度模拟程序2.0

                                                                                   实验三 进程调度模拟程序2.0 一.实验目 ...

  9. 操作系统之进程管理:15、哲学家进餐问题

    15.哲学家进餐问题 问题描述 解题思路 解决死锁的策略 方案一与方案二 方案三 注 问题描述 解题思路 1.因为需要左手和右手俩只筷子,所以可以直接拿哪只就对哪只上锁 问题:这样的话当每个人都拿走左 ...

最新文章

  1. linux基础知识-链接列表
  2. python中的 2%s何意_python中的%s%是什么意思
  3. 成都(10月24日时代广场)Windows 7社区发布活动
  4. 【4】青龙面板系列教程之QQ通知机器人XDD-plus安装
  5. 浅谈inode和block与磁盘性能的初级优化
  6. Win10+GTX 1080Ti+Anaconda TensorFlow安装
  7. mysql5.7 archive安装_对于Mysql 5.7.19 winx64 ZIP Archive的运用安装详细说明
  8. 中国大学MOOC 计算机组成原理第5章 测试(下)
  9. 数据结构与算法--这个需求很简单怎么实现我不管(发散思维)
  10. Xcode 5.1 编译模拟器以及真机都能使用的静态库
  11. Spring Cloud Sleuth + Zipkin 监控微服务(一)
  12. PreferenceScreen使用
  13. 变压器综合试验台的功能到底有多强大?
  14. 如何才能让自己成为一个自律的人?
  15. Tungsten Fabric如何增强Kubernetes的网络性能
  16. JNCIS-FWV Study Guide v1.3
  17. python饿了么商家开放平台模拟网页http请求实战
  18. web ui 套件_复古UI套件
  19. JAVASE基础(十)
  20. 华为MateBook D加装硬盘和内存

热门文章

  1. 关于react hook视频讲解笔记
  2. 聊聊职场 - 个人发展
  3. #include<>和#include“ “
  4. CAD2018安装计算机黑屏,3dmax2018一打开就闪退的三种原因和解决方法
  5. ElasticSearch教程——创建索引、类型、文档
  6. 科技作者吴军:不用低效率的算法做事情
  7. kali的网络设置及三种网络模式
  8. runauto.. 病毒斗争记
  9. php搜索引擎开源源码,PHP搜索引擎源代码
  10. Anchor-based 与 Anchor-free