【《现代操作系统 第4版》】6、进程间的通信之经典的IPC问题

哲学家就餐问题

1965年,Dijkstra提出并解决了一个他称之为哲学家就餐的同步问题。这个问题可以简单地描述如下∶五个哲学家围坐在一张圆桌周围,每个哲学家面前都有一盘通心粉。由于通心粉很滑,所以需要两把叉子才能夹住。相邻两个盘子之间放有一把叉子。哲学家的动作包括思考和进餐,当一个哲学家觉得饿了时,他就试图分两次去取其左边和右边的叉子,每次拿一把,但不分次序。如果成功地得到了两把叉子,就开始吃饭,吃完后放下叉子继续思考。问∶能为每一个哲学家写一段描述其行为的程序,且决不会死锁吗?
哲学家就餐

方案1

#define N 5		          		// 哲学家个数

void philosopher(int i) {
       // 哲学家编号:0 - 4
	while(TRUE) {
   
		think();				  	// 哲学家在思考
		take_fork(i);               // 去拿左边的叉子
		take_fork((i + 1) % N);     // 去拿右边的叉子 
		eat();	                    // 哲学家在进餐
		put_fork(i);                // 放下左边的叉子
		put_fork((i + 1) % N);      // 放下右边的叉子
	}
}

如果是单线程,这段代码没有任何问题。但是如果是5个线程同时运行,假设都运行到了 P(fork[i]); ,所有的哲学家都拿到了左边的叉子,那么运行 P(fork[(i + 1) % N]); 时就会出现死锁。没有任何哲学家能够拿到右边的叉子。

方案2

为了避免死锁,拿不到右边的叉子时,就将左边的放下,这样就不会一直占有这个资源了。

#define N 5		          				// 哲学家个数

void philosopher(int i) {
       			// 哲学家编号:0 - 4
	while(TRUE) {
   
		think();				  		 // 哲学家在思考
		take_fork(i);              		 // 去拿左边的叉子
		if (fork((i + 1) % N)) {
   		 // 右边的叉子还在吗?
			take_fork((i + 1) % N);     // 去拿右边的叉子 
			break;						// 两个叉子均到手
		} else {
   
			put_fork(i);                // 放下左边的叉子
			wait_some_time();			// 等待一会
		}
		
		
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值