n哲学家进餐问题描述有五个哲学家,他们的生活方式是交替地进行思考和进餐,n哲学家们共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,n平时哲学家进行思考,饥饿时便试图取其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐,n进餐完毕,放下筷子又继续思考。

约束条件

(1)只有拿到两只筷子时,哲学家才能吃饭。

(2)如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。

(3)任一哲学家在自己未拿到两只筷子吃饭前,不会放下手中拿到的筷子。

问题的产生

如果5个哲学家同时拿起了左边的筷子,

那么5个哲学家同时又会请求右手边的筷子,

由于每个哲学家都只有一个筷子,无法进餐,又连续的请求右手边没有的筷子,就会一直进入等待的状态(死锁)

这样5个哲学家就饿死了

在IPC进程通信中我们了解过,我们可以把五个哲学家想象成五个进程,而那五个筷子就是临界区的临界资源,

只有某个进程得到临界区的两个资源才能进行下去,否则会一直阻塞,那么就可以用一组 5个 信号量表示5个筷子,每个信号量的值为0或1 表示此筷子是否被使用中

#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h> #include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h> union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
}; #define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while (0) int sem_p(int semid)
{
struct sembuf sops = {0, -1, 0};
int ret;
ret = semop(semid, &sops, 1);
if(ret == -1)
ERR_EXIT("semop"); return 0;
} int sem_v(int semid)
{
struct sembuf sops = {0, 1, 0};
int ret;
ret = semop(semid, &sops, 1);
if(ret == -1)
ERR_EXIT("semop"); return 0;
} #define DELAY (rand()%5 + 1)
int semid; void wait_for_2fork(int no)
{
int left = no;
int right = (no+1)%5; struct sembuf buf[2] = {
{left, -1, 0},
{right, -1, 0}
}; semop(semid, buf, 2);
} void free_2fork(int no)
{
int left = no;
int right = (no+1)%5; struct sembuf buf[2] = {
{left, 1, 0},
{right, 1, 0}
}; semop(semid, buf, 2);
} void philosophere(int no)
{
srand(getpid());
for(;;)
{
printf("%d is thinking...\n", no);
sleep(DELAY);
printf("%d is hangry\n", no); wait_for_2fork(no);
printf("%d is eating\n",no);
free_2fork(no);
}
} int main(int argc, char* argv[])
{ semid = semget(IPC_PRIVATE, 5, IPC_CREAT|0666);
if(semid == -1)
ERR_EXIT("semget"); int i;
union semun su;
su.val = 1;
for(i=0; i<5; ++i)
{
semctl(semid, i, SETVAL, su);
} int no = 0;
pid_t pid;
for(i=1; i<5; ++i)
{
pid = fork();
if(pid == -1)
ERR_EXIT("fork"); if(pid == 0)
{
no = i;
break;
}
} philosophere(no); return 0;
}

最新文章

  1. zookeeper集群安装与配置
  2. TenxCloud时速云.htaccess不起作用的解决办法
  3. 06-Java 本地文件操作
  4. 黄聪:NaviCat通过Http方式连接服务器的MySQL数据库(转)
  5. Winform模拟post请求和get请求登录网站
  6. Winform控件Enable=false显示优化
  7. Swift开发之 使用系统的TabbarController
  8. jquery之null的数组
  9. redhat6.3 64位更新源(使用网易源)全过程记录
  10. 举例说,在命令模式(Command Pattern)
  11. mysql子查询慢的问题
  12. CSS -- 练习(待续优化)
  13. extremecomponents
  14. 翻译 异步I/O不会创建新的线程
  15. 线程池、进程池(concurrent.futures模块)和协程
  16. PHP+MySql+Bootstrap实现用户界面数据的删除、修改与批量选择删除——实例操作
  17. tensorflow 在加载大型的embedding模型参数时,会遇到cannot be larger than 2GB
  18. Python 函数(可变参数)
  19. 洛谷P1216 数字三角形【dp】
  20. Python 模块(module)

热门文章

  1. 使用 chart 部署 skywalking
  2. texlive支持中文的简单方法
  3. .NET进阶篇-语言章-2-Delegate委托、Event事件
  4. asp.net 开源工作流-ccflow关于 &ldquo; 是否自动计算未来的处理人&rdquo;的功能变更
  5. slf4j+logback&amp;logback.xml
  6. 【TencentOS tiny】深度源码分析(8)——软件定时器
  7. 洛谷 P1717 钓鱼
  8. 尹吉峰:使用 OpenResty 搭建高性能 Web 应用
  9. Zookeeper未授权访问测试
  10. node.js当中的http模块与url模块的简单介绍