哲学家就餐问题

这是由计算机科学家Dijkstra提出的经典死锁场景。
原版的故事里有五个哲学家(不过我们写的程序可以有N个哲学家),这些哲学家们只做两件事--思考和吃饭,他们思考的时候不需要任何共享资源,但是吃饭的时候就必须使用餐具,而餐桌上的餐具是有限的,原版的故事里,餐具是叉子,吃饭的时候要用两把叉子把面条从碗里捞出来。很显然把叉子换成筷子会更合理,所以:一个哲学家需要两根筷子才能吃饭。
现在引入问题的关键:这些哲学家很穷,只买得起五根筷子。他们坐成一圈,两个人的中间放一根筷子。哲学家吃饭的时候必须同时得到左手边和右手边的筷子。如果他身边的任何一位正在使用筷子,那他只有等着。
假设哲学家的编号是A、B、C、D、E,筷子编号是1、2、3、4、5,哲学家和筷子围成一圈如下图所示:


由于筷子位于哲学家的左右两侧,五支筷子模拟为循环链表模型,解决第一个哲学家对应1和5的筷子,这里可不必使用循环链表模型,只是本人想练练手。

共享资源:存放筷子的循环链表、finsih标志已有多少哲学家完成就餐。

主线程:初始化信号量(链表)、初始化循环链表结构、创建5个子线程(哲学家)、循环等待所有哲学家就餐完毕(finish标志)

子线程:思考(随机时间)、根据哲学家的座位获得对应的左右筷子的位置、加锁、P操作并且finsih++、解锁、V操作、完成就餐

本代码有可能造成死锁,当五个人均获取左筷子时。可优化,这个只是一个小的改动,大家多思考,方法有很多,例如可以让哲学家按顺序就餐等

附上代码

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>#define NUM 5typedef struct Node{struct Node *next;sem_t chopsticks;
}node;typedef struct list_cycle{node header;int length;
}list_cyc;int finish = 0;
pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER;
char philosophers[NUM] = {'A','B','C','D','E'};
list_cyc *list;
node n[NUM];void sys_err(char *str)
{perror("str");exit(-1);
}//遍历链表
sem_t traverse(const unsigned char num)
{int i;sem_t ret;node *cur = (node *)&list->header;for(i = 0; i < num; i++){cur = cur->next; }ret = cur->chopsticks;return ret;
}
//哲学家就餐
void *philosopher(void *arg)
{char phil = *(char *)arg;int thk_time = rand()%10;unsigned char num = phil - 'A' + 1;sem_t left = traverse(num);sem_t right = traverse(num + 1);printf("philosopher %c num %u waitting %d\n",phil,num,thk_time);sleep(thk_time);//思考pthread_mutex_lock(&mlock);sem_wait(&left);printf("philosopher %c fetches chopstick %d\n",phil,num);sem_wait(&right);printf("philosopher %c fetches chopstick %d\n",phil,num + 1);finish++;pthread_mutex_unlock(&mlock);sem_post(&left);sem_post(&right);printf("philosopher %c releases chopstick %d %d\n",phil,num, num + 1);return NULL;
}int main(void)
{int i = 0;srand(time(NULL));pthread_t tid[5];pthread_attr_t attr;list = (list_cyc *)calloc(1,sizeof(list_cyc));for(i = 0; i < NUM; i++){sem_init(&n[i].chopsticks,0,1);}list->header.next = &n[0];for(i = 0; i < NUM - 1; i++){n[i].next = &n[i+1];list->length++;}n[i].next = &n[0];list->length++;pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);for(i = 0; i < 5; i++){pthread_create(&tid[i], &attr, philosopher, &philosophers[i]);}printf("main pthread waitting\n");while(finish != 5);for(i = 0; i<NUM; i++){sem_destroy(&n[i].chopsticks);}pthread_mutex_destroy(&mlock);printf("the dining is ending ...\n");return 0;
}

哲学家就餐(linux多线程)相关推荐

  1. 哲学家就餐 linux实现_Linux哲学的9个主要原则如何影响您

    哲学家就餐 linux实现 上一次,我在Linux哲学的影响中讨论了Linux哲学的较高层次的观点. 关于它有一些非常好的讨论,许多博客联合了Opensource.com. 我从上一篇文章中收到的评论 ...

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

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

  3. linux多线程编写哲学家,Linux系统编程(三) ------ 多线程编程

    一.线程的创建和调度 1.线程是程序执行的某一条指令流的映像. 为了进一步减少处理机制的空转时间,支持多处理器及减少上下文切换开销,进程在演化中出现了另一个概念--线程.它是进程内独立的一条运行路线, ...

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

    哲学家就餐问题C语言实现(涉及多线程.信号量等) 1.实验原理 2.实验内容 3.代码部分 3.1 重要代码展示 3.2 源码 3.3 运行结果展示 1.实验原理   由Dijkstra提出并解决的哲 ...

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

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

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

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

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

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

  8. 《Linux多线程服务端编程:使用muduoC++网络库》学习笔记

    文章目录 第1章 线程安全的对象生命期管理 1.1 当析构函数遇到多线程 1.1.1 线程安全的定义 1.1.3 线程安全实例 1.2 对象的创建很简单 1.3 销毁很难 1.4 线程安全的Obser ...

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

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

最新文章

  1. linux删除目录所有内容,如何从Linux上的目录中删除所有内容
  2. 深度学习 Deep LearningUFLDL 最新Tutorial 学习笔记 2:Logistic Regression
  3. 【vijos】P1448 校门外的树
  4. react native与webview通信跳转页面报错:Cannot read property 'setNativeProps' of undefiend
  5. Mybatis 学习日记(1)
  6. 软件物料清单 (SBOM):从透明度理念到代码落地
  7. yii2环境搭建(ubuntu下nginx+php+mysql+yii2)
  8. redis高级进阶(2)
  9. cdev 结构体、设备号相关知识解析
  10. JS向NPAPI传递参数,并返回结果
  11. java爱心效果代码来了
  12. 架构之美 | 按图索骥,就能做好架构图!
  13. RGMII通信接口详述
  14. php+mysql+H5砸金蛋、九宫格、翻翻乐、扭蛋机,开盲盒抽奖程序模板
  15. Chap1_基础理论+Chap2_数据准备和数据模型
  16. 前端程序员拿到新电脑第一天,该做些什么?
  17. 第二课:为什么要教授财务知识
  18. win10右键打不开显示设置和个性化的解决教程
  19. 虎年啦,小老虎5分钟带你学会Linux中的移动-改名(mv)
  20. JavaScript从入门到放弃到精通

热门文章

  1. 自认为最中肯的“北大”评价吧(转)
  2. 关于FIN_WAIT1---TCP四次挥手的状态
  3. Logistic Regression (LR) 详解
  4. 原生js制作扫雷-自定义难度
  5. 为 Revit API 插件创建 WPF 窗口的基本项目(Revit API+WPF 系列 2/3)
  6. 详解TCP之listen
  7. 谈谈百度的短视与无奈
  8. C++中 char* 、string、 char、char[]在各种情况下的输入与输出
  9. android 霍尔传感器,浅析MTK hall霍尔传感器之原理
  10. 精英主义 遗传算法 matlab,遗传算法优化 - osc_lfs4vsih的个人空间 - OSCHINA - 中文开源技术交流社区...