1、实验原理

  由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。该问题是描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐完毕,放下筷子继续思考。

2.实验内容:

显示出每个哲学家的工作状态,如吃饭,思考。连续运行30次以上都未出现死锁现象。

3.分析解决方案一:

现在引入问题的关键:这些哲学家很穷,只买得起五根筷子。他们坐成一圈,两个人的中间放一根筷子。哲学家吃饭的时候必须同时得到左手边和右手边的筷子。如果他身边的任何一位正在使用筷子,那他只有等着。所以我们就假设最多只有4民哲学家在进餐这样就能保证没有死锁的情况。

代码如下:

  1. 1 #include<unistd.h>
  2. 2 #define NUM 5
  3. 3 int ID[NUM]={0,1,2,3,4};
  4. 4 sem_t sem_chopsticks[NUM];
  5. 5 sem_t sem_eaters;
  6. 6 int eaters_num=0;//记录已经吃过饭的次数
  7. 7
  8. 8 //初始化信号量函数
  9. 9 void sem_signal_init(){
  10. 10 int i;
  11. 11 for(i=0;i<NUM;i++){
  12. 12 if(sem_init(&sem_chopsticks[i],0,1)==-1){
  13. 13 perror("oops:em_init error!");
  14. 14 exit(1);
  15. 15 }
  16. 16 }
  17. 17 if(sem_init(&sem_eaters,0,NUM-1)==-1){
  18. 18 perror("oops:em_init error!");
  19. 19 exit(1);
  20. 20 }
  21. 21
  22. 22
  23. 23 }
  24. 24
  25. 25
  26. 26
  27. 27 //执行函数,每个线程相当于一个哲学家 来进行
  28. 28 void * philosopher(void *ptid){
  29. 29 int pthread_id=*(int *)ptid%NUM;
  30. 30 printf("%d philosopher is thinking...\n",(int)pthread_id);
  31. 31 sem_wait(&sem_eaters);
  32. 32 //申请左筷子
  33. 33 sem_wait(&sem_chopsticks[pthread_id]);
  34. 34 printf("%d philosopher takes chopstick %d...\n",(int)pthread_id,(int)pthread_id);
  35. 35 //申请右筷子
  36. 36 sem_wait(&sem_chopsticks[(pthread_id+1)%NUM]);
  37. 37 printf("%d philosopher takes chopstick %d...\n",(int)pthread_id,((int)pthread_id+1)%NUM);
  38. 38 printf("%d philosopher is eating, %d philosopher had already dined.\n",(int)pthread_id,eaters_num);
  39. 39 sem_post(&sem_chopsticks[(pthread_id+1)%NUM]) ;
  40. 40 sem_post(&sem_chopsticks[pthread_id]);
  41. 41 sem_post(&sem_eaters);
  42. 42 eaters_num++;//吃过一次的人加加
  43. 43 printf("%d philosopher had dined, by now %d philosopher had already dined.\n",(int)pthread_id,eaters_num);
  44. 44
  45. 45 }
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50 int main(int argc,char *argv[]){
  51. 51 int i,l,j,k;
  52. 52 //循环五个线程多少次
  53. 53 for(l=0;l<1;++l){
  54. 54 printf("*******%d times try *******",l+1);
  55. 55 pthread_t philosopher_threads[NUM];
  56. 56 sem_signal_init();
  57. 57 //循环创建五个线程并执行
  58. 58 for(i=0;i<NUM;i++){
  59. 59
  60. 60 printf("%d times\n",i);
  61. 61 if(pthread_create(&philosopher_threads[i],NULL,philosopher,&ID[i])!=0){
  62. 62 perror("oops:pthread_create error!");
  63. 63 exit(1);
  64. 64
  65. 65 }
  66. 66
  67. 67
  68. 68 }
  69. 69
  70. 70 //父线程等待子线程都结束才继续执行
  71. 71 for(j=0;j<NUM;j++){
  72. 72 pthread_join(philosopher_threads[j],NULL);
  73. 73 }
  74. 74 //结束销毁信号量
  75. 75 sem_destroy(&sem_eaters);
  76. 76 for(k=0;k<NUM;++k){
  77. 77 sem_destroy(&sem_chopsticks[k]);
  78. 78 }
  79. 79 eaters_num=0;
  80. 80 sleep(2);
  81. 81
  82. 82
  83. 83 }
  84. 84
  85. 85
  86. 86
  87. 87 return 0;
  88. 88 }

运行结果如下:

  1. 1 philosopher is thinking...
  2. 0 philosopher takes chopstick 0...
  3. 3 times
  4. 1 philosopher takes chopstick 1...
  5. 2 philosopher is thinking...
  6. 4 times
  7. 1 philosopher takes chopstick 2...
  8. 1 philosopher is eating, 0 philosopher had already dined.
  9. 3 philosopher is thinking...
  10. 4 philosopher is thinking...
  11. 1 philosopher had dined, by now 1 philosopher had already dined.
  12. 2 philosopher takes chopstick 2...
  13. 0 philosopher takes chopstick 1...
  14. 0 philosopher is eating, 1 philosopher had already dined.
  15. 4 philosopher takes chopstick 4...
  16. 3 philosopher takes chopstick 3...
  17. 0 philosopher had dined, by now 2 philosopher had already dined.
  18. 4 philosopher takes chopstick 0...
  19. 4 philosopher is eating, 2 philosopher had already dined.
  20. 4 philosopher had dined, by now 3 philosopher had already dined.
  21. 3 philosopher takes chopstick 4...
  22. 3 philosopher is eating, 3 philosopher had already dined.
  23. 3 philosopher had dined, by now 4 philosopher had already dined.
  24. 2 philosopher takes chopstick 3...
  25. 2 philosopher is eating, 4 philosopher had already dined.
  26. 2 philosopher had dined, by now 5 philosopher had already dined.
  27.  
  28. --------------------------------
  29. Process exited after 2.127 seconds with return value 0
  30. 请按任意键继续. . .

后续方案将继续更新请关注!!!

linux c语言 哲学家进餐---信号量PV方法一的更多相关文章

  1. Linux下IPC中的信号量PV操作

    代码如下所示,两边对照查看程序!(左图为先运行进程 右图为后运行进程)    运行的效果就是:当左边的进程检测到EOF,释放资源V操作之后,右边的进程会迅速的执行对应的printf的操作! 所有代码文 ...

  2. 利用Linux下的pthread_mutex_t类型来实现哲学家进餐问题

    首先说一下什么是哲学家进餐问题,这是操作系统课程中一个经典的同步问题, 问题如下:如上图,有6个哲学家和6根筷子(那个蓝色部分表示哲学家,那个紫色长条部分表示筷子),他们分别被编了0~5的号!如果某个 ...

  3. Java哲学家进餐问题|多线程

    Java实验三 多线程 哲学家进餐问题: 5个哲学家共用一张圆桌,分别坐在周围的5张椅子上, 在圆桌上有5个碗和5只筷子(注意是5只筷子,不是5双), 碗和筷子交替排列.他们的生活方式是交替地进行思考 ...

  4. 转载~kxcfzyk:Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解

    Linux C语言多线程库Pthread中条件变量的的正确用法逐步详解   多线程c语言linuxsemaphore条件变量 (本文的读者定位是了解Pthread常用多线程API和Pthread互斥锁 ...

  5. java笔记--超级类Object多线程的应用+哲学家进餐算法内部类与多线程结合

    关于Object类中的线程方法: Object类是所有Java类的 父类,在该类中定义了三个与线程操作有关的方法,使得所有的Java类在创建之后就支持多线程 这三个方法是:notify(),notif ...

  6. Linux C语言操作MySQL

    原文:Linux C语言操作MySQL 1.MySQL数据库简介 MySQL是一个开源码的小型关系数据库管理系统,体积小,速度快,总体成本低,开源.MySQL有以下特性: (1) 使用C和C++编写, ...

  7. linux c语言定时器

    原文来自于:http://hi.baidu.com/opetrhsxszbckzd/item/126966cae5f9524aa9ba94f5 我只是把其重新排版标注一下. linux c语言定时器 ...

  8. Linux改变语言设置的命令

    --Linux语言设置--------------2013/09/22Linux中语言的设置和本地化设置真是一个很繁琐的事情,时不时的会出现乱码的情况,在这篇文章中讨论的是shell中出现乱码的一些解 ...

  9. 第4章 同步控制 Synchronization ---哲学家进餐问题(The Dining Philosophers)

    哲学家进餐问题是这样子的:好几位哲学家围绕着餐桌坐,每一位哲学家要么思考,要么等待,要么就吃饭.为了吃饭,哲学家必须拿起两支筷子(分放于左右两端).不幸的是,筷子的数量和哲学家相等,所以每支筷子必须由 ...

随机推荐

  1. css实现中间横线俩边文字效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 多测师讲解_肖sir _rf报错归纳(1):

    错误一: 报错原因:文件格式 解决方案: 修改文件格式,将txt改成robot格式   错误二: rf 运行以后出现乱码现象 解决方案: 打开python的安装路径下:C:\python37\Lib\ ...

  3. 多测师讲解pthon_002字符,列表,元组,字段等

    # # # 索引:# # # 正向索引:  0  1  2  3  4  5  6# # #      l=   a  b  c  d  e  f  g# # # 反向索引: -7 -6 -5 -4 ...

  4. MeteoInfoLab脚本示例:OMI Swath HDF数据

    这个例子读取OMI卫星Swath数据中的CloudFaction变量并绘图.脚本程序: #Add data file folder = 'D:/Temp/hdf/' fns = 'OMI-Aura_L ...

  5. Jmeter请求之接口串联自动化测试(未完)

    方案一:添加Cookie管理器,把用户的登录状态存在cookie管理器中,类似于浏览器 存储测试结果: 监听器->保存响应到文件,对结果进行存储 文件名前缀:保存到哪个地方前缀是什么D:\tes ...

  6. 【线段树】BZOJ 5334 数学计算

    题目内容 小豆现在有一个数\(x\),初始值为\(1\).小豆有\(Q\)次操作,操作有两种类型: 1 m:\(x=x×m\),输出\(x\ mod\ M\): 2 pos:\(x=x/\)第\(po ...

  7. rabbitmq之后台管理和用户设置

    前言 前面介绍了erlang环境的安装和rabbitmq环境安装,接下来介绍rabbitmq的web管理和用户设置. 启用后台管理插件 通过后台管理插件我们可以动态监控mq的流量,创建用户,队列等. ...

  8. centos8安装sersync为rsync实现实时同步

    一,查看本地centos的版本: [root@localhost lib]# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) ...

  9. xpath取末尾

    from lxml import etree html = ''' <!DOCTYPE html> <html lang="en"> <head> ...

  10. Python之包的相关

    包的产生: 由于模块不断更新,越写越大,仅用单个py文件会使模块逻辑不够清晰,所以需要将模块的不同功能放入不同的py文件,然后将所有py文件放在一个目录内,这个目录就是包 包就是一个包含用__init ...