哲学家就餐问题C语言实现(涉及多线程、信号量等)

  • 1、实验原理
  • 2、实验内容
  • 3、代码部分
    • 3.1 重要代码展示
    • 3.2 源码
    • 3.3 运行结果展示

1、实验原理

  由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。该问题是描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐完毕,放下筷子继续思考。

2、实验内容

  显示出每个哲学家的工作状态,如吃饭,思考。连续运行30次以上都未出现死锁现象。

3、代码部分

3.1 重要代码展示

重要代码展示:
(1)初始化int型数组ID[NUM]标识线程ID号,用于后续传参;初始化信号量数组sem_chopsticks[NUM]模拟五根筷子;初始化信号量sem_eaters=4,用来控制同时可拿起筷子的最大人数。

int ID[NUM]={0,1,2,3,4};
sem_t sem_chopsticks[NUM];
sem_t sem_eaters;
sem_init(&sem_eaters,0,NUM-1)

(2)线程的例程处理函数,先等待信号量sem_eaters,再等待信号量sem_chopsticks[pthread_id],这两个信号量不为零说明此时同时拿起筷子的人数小于4,且该哲学家编号相同的筷子(记为左筷子)可以被拿起,所以拿起左子,然后等待右筷子sem_chopsticks[pthread_id+1]信号量,拿到右筷子后便可以进餐,随机释放上述三个信号量。

void philosopher(void * ptid){int pthread_id = *(int *)ptid%NUM;printf("%d philosopher is thinking...\n",(int)pthread_id);sem_wait(&sem_eaters);sem_wait(&sem_chopsticks[pthread_id]);printf("%d philosopher takes chopstick %d...\n",(int)pthread_id,(int)pthread_id);sem_wait(&sem_chopsticks[(pthread_id+1)%NUM]);printf("%d philosopher takes chopstick %d...\n",(int)pthread_id,((int)pthread_id+1)%NUM);
printf("%d philosopher is eating, %d philosopher had already dined.\n",(int)pthread_id,eaters_num);sem_post(&sem_chopsticks[(pthread_id+1)%NUM]);sem_post(&sem_chopsticks[pthread_id]);sem_post(&sem_eaters);eaters_num++;printf("%d philosopher had dined, by now %d philosopher had already dined.\n",(int)pthread_id,eaters_num);}

(3)循环创建5个线程模拟五位哲学家,线程例子程函数为philosopher,并传入参数ID[i]标识线程的ID。

pthread_t philosopher_threads[NUM];sem_signal_init();for ( i= 0; i < NUM; i++) {printf("%d times\n",i);if (pthread_create(&philosopher_threads[i], NULL, (void *)&philosopher,&ID[i]) != 0){perror("oops:pthread_create error!");exit(1);}

3.2 源码

#include <unistd.h>
#include "pthread.h"
#include "stdio.h"
#include "stdlib.h"
#include "semaphore.h"#define NUM 5
int ID[NUM]={0,1,2,3,4};
sem_t sem_chopsticks[NUM];
sem_t sem_eaters;
int eaters_num=0;
void sem_signal_init(){int i;for (i=0; i<NUM; i++){if (sem_init(&sem_chopsticks[i],0,1) == -1){perror("oops:em_init error!");exit(1);}}if (sem_init(&sem_eaters,0,NUM-1) == -1){perror("oops:em_init error!");exit(1);}
}void philosopher(void * ptid){int pthread_id = *(int *)ptid%NUM;printf("%d philosopher is thinking...\n",(int)pthread_id);sem_wait(&sem_eaters);sem_wait(&sem_chopsticks[pthread_id]);printf("%d philosopher takes chopstick %d...\n",(int)pthread_id,(int)pthread_id);sem_wait(&sem_chopsticks[(pthread_id+1)%NUM]);printf("%d philosopher takes chopstick %d...\n",(int)pthread_id,((int)pthread_id+1)%NUM);printf("%d philosopher is eating, %d philosopher had already dined.\n",(int)pthread_id,eaters_num);sem_post(&sem_chopsticks[(pthread_id+1)%NUM]);sem_post(&sem_chopsticks[pthread_id]);sem_post(&sem_eaters);eaters_num++;printf("%d philosopher had dined, by now %d philosopher had already dined.\n",(int)pthread_id,eaters_num);}int main(){int i,l,j,k;for (l = 0; l < 1000; ++l) {printf("**********************%d times try ******************************",l+1);pthread_t philosopher_threads[NUM];sem_signal_init();for ( i= 0; i < NUM; i++) {printf("%d times\n",i);if (pthread_create(&philosopher_threads[i], NULL, (void *)&philosopher,&ID[i]) != 0){perror("oops:pthread_create error!");exit(1);}}for ( j = 0; j < NUM; j++) {pthread_join(philosopher_threads[j], NULL);}sem_destroy(&sem_eaters);for (k = 0; k < NUM ; ++k) {sem_destroy(&sem_chopsticks[k]);}eaters_num = 0;
//        sleep(2);}return 0;
}

3.3 运行结果展示

  本程序用五个线程模拟五位哲学家,用五个sem_t型信号量模拟五根筷子(临界资源),解题的思想是:每次让每位哲学家优先拿起自己左边的筷子,并限制最多有四个人同时拿起筷子,从而避免了死锁情况,该程序模拟五个哲学家进餐一次的情况,并重复模拟了1000次以上来检验是否出现死锁情况,经检验程序运行正常,没有出现死锁状况,上述图片仅展示了第1次和第1000次的情况。

哲学家就餐问题C语言实现(涉及多线程、信号量等)相关推荐

  1. 哲学家就餐问题c语言_哲学家就餐问题的一种Python解决方案

    哲学家就餐问题一直是多线程同步问题的经典案例,本文中展示了多线程竞争共享资源带来的死锁问题,并介绍了一种简单的解决方案. 哲学家就餐问题 哲学家最擅长的就是思考和吃饭 ,当他们感觉累的时候,就会拿起一 ...

  2. 哲学家就餐问题(如何避免死锁)(多线程版)

    哲学家就餐问题 多线程编程中,常常会遇到线程间访问共享资源的问题,如果处理不当则会发生死锁,某一个线程可能永远访问不到共享资源. 为了避免死锁的发生,提出哲学家就餐问题. 下面展示一些代码片段 #in ...

  3. Java多线程学习四十二:有哪些解决死锁问题的策略和哲学家就餐问题

    线上发生死锁应该怎么办 如果线上环境发生了死锁,那么其实不良后果就已经造成了,修复死锁的最好时机在于"防患于未然",而不是事后补救.就好比发生火灾时,一旦着了大火,想要不造成损失去 ...

  4. 哲学家就餐(linux多线程)

    哲学家就餐问题 这是由计算机科学家Dijkstra提出的经典死锁场景. 原版的故事里有五个哲学家(不过我们写的程序可以有N个哲学家),这些哲学家们只做两件事--思考和吃饭,他们思考的时候不需要任何共享 ...

  5. 多线程“死锁”之“哲学家就餐”代码实现

    死锁:就是两个或者两个以上的线程相互占用对方的需要的资源,而不进行释放,导致彼此都在等待对方释放资源,产生了无限制的等待的现象. "哲学家就餐"的问题不在赘述,可以自行百度或者Go ...

  6. 多线程之哲学家就餐问题(java代码含注释)

    什么是哲学家就餐问题 有五个哲学家在一张桌上,他们交替思考和吃饭.每个人只能拿自己左右手边的叉子,当他们拿到两只叉子的时候才能吃饭,吃完饭就放下叉子开始思考,每个哲学家不能同时拿起两只叉子.用程序实现 ...

  7. Thinking in Java---从哲学家就餐问题看死锁现象

    我们知道一个对象可以有synchronized方法或其他形式的加锁机制来防止别的线程在互斥还没释放的时候就访问这个对象.而且我们知道线程是会变成阻塞状态的(挂起),所以有时候就会发生死锁的情况:某个任 ...

  8. 哲学家就餐问题实验报告

    哲学家就餐问题 两个地方应该是pv操作,pv都是操作元语,不可中断 p操作是将信号量-1 v操作是将信号量+1 pv一定要配对使用 哲学家进餐可以通过信号量机制解决,避免死锁 注释如下: test(i ...

  9. 哲学家进餐问题pv_【jMiniLang】哲学家就餐问题

    演示GIF(1.57MB),控制台输出效果(还有parser/vm/ui)自己实现: 信号量与PV原语 信号量为正数代表有空闲资源,为零与负数代表没有空闲资源.负数的绝对值代表等待的进程个数.信号量用 ...

最新文章

  1. php 发送微信请求失败的原因,微信小程序模拟正常 真机服务器请求出错
  2. 前端程序员如何选择适合自己的培训机构
  3. python3 threading.lock_Python3 threading
  4. mysql数据库基础简介_MySQL数据库之MySQL 基础之MySQL简介
  5. 【Excel-2010】导入网站数据
  6. python在win10怎么搭建_Win10下Python环境搭建与配置教程
  7. apt安装openjdk8
  8. QCC---Temperature component
  9. vue 全年日历显示并且日期批量选择
  10. 一步步用python制作游戏外挂 - blueel - 博客园
  11. 通常所说的微型计算机的主机主要包括(),微型计算机的主机主要包括
  12. 计算机网络小黑指北-单选题自测
  13. java网课|Iterator接口
  14. K_A16_001 基于STM32等单片机驱动HX711称重模块 串口与OLED0.96双显示
  15. 高龄白菜java学习第101天(java数据结构和算法(19))
  16. vue设置右边距_利用页面布局设置制作工资条(不用函数)
  17. Content type 'multipart/form-data;boundary=----WebKitF;charset=UTF-8' not supported
  18. GitHub统计代码量
  19. Acrel-3200远程预付费电能管理系统 在福州万宝产业园的应用
  20. adb window10 配置环境变量

热门文章

  1. 强烈推荐 | 程序员七大生产力工具
  2. RK3568平台开发系列讲解(设备驱动篇)V4L2程序实现流程
  3. linux网卡灯不亮怎么处理,电脑网卡灯不亮怎么办 电脑网卡灯不亮解决方法介绍【详解】...
  4. tensorflow独热编码方法_tf.one_hot()用法 独热编码
  5. 高德/百度经纬度转换
  6. java 城市分词_Java中文分词hanlp使用
  7. layui数据表格某个字段不显示问题
  8. three.js和高德地图结合引入obj格式模型-效果演示
  9. JsonResult工具类
  10. 如何使用 datax 将 mysql 中的数据拉取到 hive ?