场景:

原版的故事里有五个哲学家(不过我们写的程序可以有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是毫秒级的阻塞

最新文章

  1. AutoMapper随笔记
  2. 【Oracle】去除表中重复的数据
  3. uva 11806 Cheerleaders
  4. HttpURLConnection使用getInputStream无法执行
  5. IntelliJ IDEA 13试用手记(附详细截图)
  6. libtcc使用问题一二
  7. 前端MVC学习总结(四)——NodeJS+MongoDB+AngularJS+Bootstrap书店示例
  8. Python操作列表的常用方法
  9. 03_HttpClient_Post请求
  10. 深刻理解C#的传值调用和传引用调用
  11. CentOS环境下,gdb调试中出现:Missing separate debuginfos, use: debuginfo-install.....的问题
  12. javascript获取CSS3浏览器前缀
  13. App如何选择移动广告平台,开发者2 - 移动变现模式分析
  14. firefly rk3288 内核模块编译
  15. C# 打印PDF文档的10种方法
  16. Confluence 6 站点高级自定义
  17. Hive| 查询
  18. 【LGP5176】公约数
  19. android textview字体加粗 Android studio最新水平居中和垂直居中
  20. Tomcat 动态数据库连接池

热门文章

  1. 在Eclipse Android中设置模拟器屏幕大小
  2. jQuery BlockUI Plugin Demo 3(Page Blocking Examples)
  3. laydate时间控件:开始时间,结束时间最大最小值
  4. 【C/C++开发】运算符重载二
  5. css实现可伸缩的搜索框
  6. UiPath工具当中写入代码
  7. K8S从入门到放弃系列-(12)Kubernetes集群Coredns部署
  8. (二)javaweb开发的常见概念总结(来自那些年的笔记)
  9. pause的作用
  10. CSS之cursor用法