并发编程 - 哲学家就餐问题

本文通过模拟五个哲学家围绕一张圆桌进餐的情景,探讨并发处理中的死锁与无饥饿问题。每个哲学家被视为一个线程,筷子作为共享资源。文章提供了避免死锁和饥饿现象的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

哲学家就餐问题

哲学家就餐问题是由并发处理的先驱E.W.Dijkstra所提出,主要用于阐述死锁无饥饿概念。假设五个哲学家一生只在思考和就餐。他们围坐在一个大圆桌旁,桌上有一大盘米饭。然而只有五根可用的筷子。所有的哲学家都在思考。若某个哲学家饿了,则拿起身边的两根筷子。如果他能够拿到这两根筷子,则可以就餐。当这个哲学家吃完后,又放下自己生变的两根筷子。如果他能够拿到这两根筷子,则可以就餐。当这个哲学家吃完后,又放下筷子继续思考。

  1. 试编写模仿哲学家就餐行为的程序,其中给每一个哲学家为一个线程而筷子则是共享对象。注意,必须防止出现两个哲学家同时使用一根筷子的情形。
  2. 修改所编写的程序,不允许出现死锁情况,也就是说,保证不会出现这样的情况:每个哲学家都已拥有一根筷子,并且在等待获得另一个人手中的筷子。
  3. 修改所编写的程序使得不会出现饥饿现象。
  4. 编写能够保证任意n个哲学家无饥饿就餐的程序。

解题思路:

  • 筷子属于两个哲学家的共享资源,定义为全局变量。
  • 这里的锁相关函数没有实现,这里就当做伪代码来看吧。
  • 一个哲学家需要先看左手边的筷子,当左边的筷子没有人使用时拿起。
    右边同理。
    这时,哲学家有三个状态。
  1. 没有拿着筷子
  2. 拿到了一根筷子
  3. 幸运的拿到了两根筷子
    这时,当处于③状态时,就可以开心的吃饭了。吃完以后,将筷子放下,让别人使用。
    当处于②状态时,一直拿着这根筷子会制造饥饿。所以,在看到只能拿到一只筷子时,就再将它放下,可供其他人使用。
    ①状态,就只能等两边的人把筷子放下来了。
    这个过程应该就能满足以上四个条件了。

代码

//全局的筷子信息
int Chopsticks[poilosophers]; //需要提前知道哲学家的人数,用动态数组在指定的初始化函数进行分配也行
/**
* poilosopherId 哲学家编号0,1,2,3,4
* poilosophers 哲学家个数,譬如5个
* /
void selectChopsticks(int poilosopherId, int poilosophers){
	//1. l_chopstick左边的筷子,r_chopstick右边筷子
	int l_chopstick = poilosopherId, r_chopstick = poilosopherId + 1;
	//2. 保持环状
	if (r_chopstick == poilosophers){
		r_chopstick -= poilosophers; 
	}
 
	int getChopstickNum = 0, eated = 0;
	while (1){
		lock(); //加锁
		//3. 如果左边筷子空闲
		if (Chopsticks[l_chopstick] == 0){
			Chopsticks[l_chopstick] = poilosopherId;
		}
		unlock();
 
		lock();
		//4. 如果右侧筷子空闲
		if (Chopsticks[r_chopstick] == 0){
			Chopsticks[r_chopstick] = poilosopherId;
		}
		unlock();
 		//5. 如果拿到两个筷子,则吃饭
		if (Chopsticks[l_chopstick] = poilosopherId && Chopsticks[r_chopstick] == poilosopherId) {
			eated = 1;
		}
 		
 		//6. 回到初始状态0 
 		//包含两种情况: 1. 拿到两个筷子,吃完后放下筷子; 2. 拿到一支筷子,则放下.
		if (Chopsticks[l_chopstick] == poilosopherId){
			Chopsticks[l_chopstick] = 0;
		}
		if (Chopsticks[r_chopstick] == poilosopherId){
			Chopsticks[r_chopstick] = 0;
		}
 
		if (eated) break;
	}
}

QA

  • 以上代码是本人基于网上资料,加上自己的理解后的产物,仅仅为了更好的理解并发的死锁和无饥饿特性.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值