场景:

原版的故事里有五个哲学家(不过我们写的程序可以有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. jQuery BlockUI Plugin Demo 2

    Overview The jQuery BlockUI Plugin lets you simulate synchronous behavior when using AJAX, without l ...

  2. swift 屏幕的翻转 + 状态栏(statusBar)的隐藏

    1.状态栏的隐藏 这个问题是基于 UIApplication.shared.isStatusBarHidden = true; 调用居然是无效的…… 现在写下自己的代码,用来备忘吧…… 1.首先需要复 ...

  3. charles 高级批量请求

    本文参考:charles 高级批量请求 这个我感觉有点鸡肋,真正的批量请求,推荐使用JMter charles 高级批量请求就是下面这种简单的设置的 简单的使用还是可以的; 比如简单的测试下,向某一个 ...

  4. 【ARM-Linux开发】TI 关于Gstreamer使用的几个参考

    http://processors.wiki.ti.com/index.php/Example_GStreamer_Pipelines#H.264_RTP_Streaming http://proce ...

  5. 最新 哔哩哔哩java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.哔哩哔哩等10家互联网公司的校招Offer,因为某些自身原因最终选择了哔哩哔哩.6.7月主要是做系统复习.项目复盘.Leet ...

  6. 使用eclipse插件mybatis generator来自动生成实体类及映射文件

    <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE generatorConfiguratio ...

  7. 1、5 写注册的后台并写前台html&密码加密&id 随机

    1 public void save(Student student) { // TODO Auto-generated method stub student.setSid(UUID.randomU ...

  8. wireguard使用方法

    1.翻墙访问网页:https://cryptostorm.is/wireguard.cgi 并下载客户端 2. 选者第二个并打开 3.复制publickey 4.黏贴在第二行并addkey: 5.将获 ...

  9. WebElement的方法:

    这个类代表HTML页面元素 id_ #当前元素的ID tag_name #获取元素标签名的属性 text #获取该元素的文本. click() #单击(点击)元素 submit() #提交表单 cle ...

  10. Python习题002

    作业1:判断某一个字符串是否是小数 def is_float(string): string1 = str(string) if string1.count('.') > 1: #检测字符串小数 ...