场景:

原版的故事里有五个哲学家(不过我们写的程序可以有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. css3 animation 点亮灯光效果

    <style> .wrap .bulb { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50% ...

  2. 理解ADFS相关概念

    核心概念 Claims是?Token是?Security Token是?Security Token Server (STS)是? 声明与令牌无关,但通过封装在安全令牌中来进行网络传输! SSL证书是 ...

  3. 【ARTS】01_36_左耳听风-201900715~201900721

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...

  4. AWS 云上安全最佳实践

    目录 一.账号及访问管理 1.1.多 VPC 还是多账号模式 1.2.多账户模式,选择主 master 账号 二.系统架构安全 2.1.子网建议 2.2.每个可用区子网划分 2.3.安全组的建议 2. ...

  5. MVC模式实现注册登录

    很多人对MVC模式搞不懂,刚开始是我也犯迷糊,知道看到一个前辈写的代码,我顿时有的恍然大悟,拿来分享给各位 MVC: 就是M:模型.V:视图(前台界面)C:后台处理的servlet 话不多说.上代码 ...

  6. for i in range()

    for i in range()就是python中的循环语句 有以下三种常见用法: 1.range(3) [0,3)即0,1,2 2.range(1,3) [1,3)即1,2 3.range(1,5, ...

  7. Layui 上传图片到磁盘上 + Tomcat 配置虚拟路径

    Layui 上传图片到磁盘上 + Tomcat 配置虚拟路径 Tomcat 配置虚拟路径 找到 eclipse 中 tomcat 下面的 server.xml 文件,在 Host 标签里面添加 < ...

  8. java日志框架系列(9):logback框架过滤器(filter)详解

    过滤器放在了logback-classic模块中. 1.logback-classic模块中过滤器 分类(2种):常规过滤器.TurboFilter过滤器. 1.常规过滤器 常规过滤器可以通过自定义进 ...

  9. Essential C++ Reading Notes

    Chapter1 P6, 1.2 Why //#include<string> we still can use "string user_name"? -->c ...

  10. msyql 去重

    delete from userinfo where busi_id in (select busi_id from (select busi_id from userinfo group by bu ...