场景:

原版的故事里有五个哲学家(不过我们写的程序可以有N个哲学家),这些哲学家们只做两件事--思考和吃饭,他们思考的时候不需要任何共享资源,但是吃饭的时候就必须使用餐具,而餐桌上的餐具是有限的,原版的故事里,餐具是叉子,吃饭的时候要用两把叉子把面条从碗里捞出来。很显然把叉子换成筷子会更合理,所以:一个哲学家需要两根筷子才能吃饭。

现在引入问题的关键:这些哲学家很穷,只买得起五根筷子。他们坐成一圈,两个人的中间放一根筷子。哲学家吃饭的时候必须同时得到左手边和右手边的筷子。如果他身边的任何一位正在使用筷子,那他只有等着。

假设哲学家的编号是A、B、C、D、E,筷子编号是1、2、3、4、5,哲学家和筷子围成一圈如下图所示:

 
 

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <memory.h>
  4. #include <pthread.h>
  5. #include <errno.h>
  6. #include <math.h>
  7. //筷子作为mutex
  8. pthread_mutex_t chopstick[6] ;
  9. void *eat_think(void *arg)
  10. {
  11. char phi = *(char *)arg;
  12. int left,right; //左右筷子的编号
  13. switch (phi){
  14. case 'A':
  15. left = 5;
  16. right = 1;
  17. break;
  18. case 'B':
  19. left = 1;
  20. right = 2;
  21. break;
  22. case 'C':
  23. left = 2;
  24. right = 3;
  25. break;
  26. case 'D':
  27. left = 3;
  28. right = 4;
  29. break;
  30. case 'E':
  31. left = 4;
  32. right = 5;
  33. break;
  34. }
  35. int i;
  36. for(;;){
  37. usleep(3); //思考
  38. pthread_mutex_lock(&chopstick[left]); //拿起左手的筷子
  39. printf("Philosopher %c fetches chopstick %d\n", phi, left);
  40. if (pthread_mutex_trylock(&chopstick[right]) == EBUSY){ //拿起右手的筷子
  41. pthread_mutex_unlock(&chopstick[left]); //如果右边筷子被拿走放下左手的筷子
  42. continue;
  43. }
  44. //  pthread_mutex_lock(&chopstick[right]); //拿起右手的筷子,如果想观察死锁,把上一句if注释掉,再把这一句的注释去掉
  45. printf("Philosopher %c fetches chopstick %d\n", phi, right);
  46. printf("Philosopher %c is eating.\n",phi);
  47. usleep(3); //吃饭
  48. pthread_mutex_unlock(&chopstick[left]); //放下左手的筷子
  49. printf("Philosopher %c release chopstick %d\n", phi, left);
  50. pthread_mutex_unlock(&chopstick[right]); //放下左手的筷子
  51. printf("Philosopher %c release chopstick %d\n", phi, right);
  52. }
  53. }
  54. int main(){
  55. pthread_t A,B,C,D,E; //5个哲学家
  56. int i;
  57. for (i = 0; i < 5; i++)
  58. pthread_mutex_init(&chopstick[i],NULL);
  59. pthread_create(&A,NULL, eat_think, "A");
  60. pthread_create(&B,NULL, eat_think, "B");
  61. pthread_create(&C,NULL, eat_think, "C");
  62. pthread_create(&D,NULL, eat_think, "D");
  63. pthread_create(&E,NULL, eat_think, "E");
  64. pthread_join(A,NULL);
  65. pthread_join(B,NULL);
  66. pthread_join(C,NULL);
  67. pthread_join(D,NULL);
  68. pthread_join(E,NULL);
  69. return 0;
  70. }

注意:

1. gcc编译时,加上-lphread选项,例:gcc eating.c -lpthread

2.pthread_create的第四个参数是void *类型,我一开始传一个char类型,即'A',就会发生段错误。但改成char *,即“A”就没问题了。

3.usleep是毫秒级的阻塞

哲学家就餐问题 C语言实现的更多相关文章

  1. 哲学家就餐问题-Java语言实现死锁避免

    哲学家就餐问题-Java语言实现死锁避免 我死锁预防是至少破坏死锁产生的四个必要条件之一,带来的问题就是系统资源利用率低且不符合开发习惯,而死锁避免不是事先釆取某种限制措施破坏死锁的必要条件,只是注意 ...

  2. JAVA多线程学习--哲学家就餐问题

    哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题. 问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条.哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿 ...

  3. JAVA并发,经典死锁案例-哲学家就餐

    转自:http://blog.csdn.net/tayanxunhua/article/details/38691005 死锁经典案例:哲学家就餐. 这个案例会导致死锁. 通过修改<Java编程 ...

  4. linux下多线程互斥量实现生产者--消费者问题和哲学家就餐问题

    生产者消费者问题,又有界缓冲区问题.两个进程共享一个一个公共的固定大小的缓冲区.其中一个是生产者,将信息放入缓冲区,另一个是消费者,从缓冲区中取信息. 问题的关键在于缓冲区已满,而此时生产者还想往其中 ...

  5. Linux环境下实现哲学家就餐问题

    #include <stdio.h> #include <stdlib.h> #include <memory.h> #include <pthread.h& ...

  6. Java多线程,哲学家就餐问题

    问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条.哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿到两只筷子才能吃饭.上述问题会产生死锁的情况,当5个哲学家都拿起自己右手 ...

  7. 哲学家就餐-同步问题解析-python

    五个哲学家吃五盘通心粉,由于通心粉很滑,所以必须要拿起左右两边的叉子才能吃到. 叉子的摆放如图所示. 那么问题来了:能为每一个哲学家写一段描述其行为的程序,保证不会出现死锁. 解法1:让他等待能够使用 ...

  8. Linux环境下实现哲学家就餐问题(2)

    #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <string.h& ...

  9. Go语言中的互斥锁和读写锁(Mutex和RWMutex)

    目录 一.Mutex(互斥锁) 不加锁示例 加锁示例 二.RWMutex(读写锁) 并发读示例 并发读写示例 三.死锁场景 1.Lock/Unlock不是成对出现 2.锁被拷贝使用 3.循环等待 虽然 ...

随机推荐

  1. jenkins的pipeline拉取指定分支的代码

    脚本示例 pipeline { agent any options { durabilityHint 'PERFORMANCE_OPTIMIZED' timeout(time:5, unit: 'MI ...

  2. Angular 8 - 更小的包

    Angular 8 - 更小的包 Angular 8 发布 原文地址:https://blog.angular.io/version-8-of-angular-smaller-bundles-cli- ...

  3. 个人总结2019 ASP.NET面试题

    1.什么是面向对象? 面向对象就是把一个人或事务的属性,比如名字,年龄这些定义在一个实体类里面.存和取的时候直接使用存取实体类就把这个人的名字,年龄这些全部存了,这个实体类就叫对象,这种思想就叫面向对 ...

  4. 判断scrollView的滑动方向(二)

    在上一篇文章<判断scrollView的滑动方向>中谈到的第二种方法是根据滑动速率来判断的. 今天将通过滑动过程中的坐标差来判断 - (void)scrollViewDidScroll:( ...

  5. python 创建虚拟环境时报错OSError, setuptools下载失败

    错误信息如下: Using base prefix 'c:\\users\\huful\\appdata\\local\\programs\\python\\python36-32'New pytho ...

  6. python __name__ == ‘__main__’详细解释(27)

    学习过C语言或者Java语言的盆友应该都知道程序运行必然有主程序入口main函数,而python却不同,即便没有主程序入口,程序一样可以自上而下对代码块依次运行,然后python不少开源项目或者模块中 ...

  7. C#传递参数调用exe程序

    今天公司让我把Winform程序里的一块单独成一个exe文件,从原程序中打开新的exe程序,这就涉及到参数的传递,故来记录下传递参数到exe程序的方式 第一种方式 首先在程序A中添加引用using S ...

  8. LC 173. Binary Search Tree Iterator

    题目描述 Implement an iterator over a binary search tree (BST). Your iterator will be initialized with t ...

  9. php实现支付宝在线支付和扫码支付demo

    ### php实现支付宝在线支付和扫码支付demo 背景:在做一个公众号时增加了h5端,需要接入支付,非微信环境,选择了支付宝,以下简单记录下实现过程,并做了简单的封装,拿来即可使用,注意:本项目只是 ...

  10. Python开发【第五章】:常用模块

    一.模块介绍: 1.模块定义 用来从逻辑上组织python代码(变量,函数,类,逻辑:实现一个功能),本质上就是.py结尾python文件 分类:内置模块.开源模块.自定义模块 2.导入模块 本质:导 ...