哲学家就餐与经典死锁问题

哲学家就餐问题

在这里插入图片描述
死锁发生的原因:由于0号哲学家申请了左边的0号叉子,还没来得及申请到右边的1号叉子,结果1号哲学家又把左边的1号叉子抢了过去,以此类推,,,,4号哲学家申请了左边的4号叉子,又转去申请0号叉子,结果是五个哲学家都同时拿起了左叉子而拿不到右叉子,最终进入了死循环从而导致了死锁现象。为了防止这种情况发的发生,我们可以有以下两种解决方案:

解决方案一定义一个信号量,让每次只允许最多四个哲学家吃饭,这样就肯定有一个哲学家可以吃到饭,不会发生死锁现象。

解决方案二我们发现,前四个哲学家同时从小到大的顺序申请叉子,那么如果4号哲学家也和前面的哲学家一样,都是从小到大去申请叉子,也就是如果他先申请0号叉子,再去申请4号叉子,那么问题不就解决了吗。因此,我们就可以限制哲学家们申请叉子的顺序来解决死锁问题。
具体的实现代码如下:注释的部分是通过信号量解决的,未注释的是通过限制顺序实现的;

package Data;

import java.util.concurrent.Semaphore;

public class PhilosopherProblem {
	//public static final Semaphore MUTEX = new Semaphore(4); //定义一个互斥信号量(只允许四个哲学家吃饭)
	public static void main(String[] args) {
		
		Fork forks = new Fork();
		
		Philosoper p0 = new Philosoper(forks,0);
		Philosoper p1 = new Philosoper(forks,1);
		Philosoper p2 = new Philosoper(forks,2);
		Philosoper p3 = new Philosoper(forks,3);
		Philosoper p4 = new Philosoper(forks,4);
		
		p0.start();
		p1.start();
		p2.start();
		p3.start();
		p4.start();
	}
		
}
	
	class Fork{
		private Semaphore[] forks = new Semaphore[] {
		new Semaphore(1),new Semaphore(1),new Semaphore(1),new Semaphore(1),new Semaphore(1)};		
		
		//拿起叉子的方法
		public void get(int fork_no){
		try {
			forks[fork_no].acquire();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}
		
		//放下叉子的方法
		public void put(int fork_no) {
			forks[fork_no].release();
		}
		
		//获取叉子的数量
		public int getForkCount() {
			return forks.length;
		}
	 }		
		class Philosoper extends Thread{
			private int no;
			private Fork forks;
			public Philosoper(Fork forks, int no) {
				this.no = no;
				this.forks = forks;
			}
			public void run() {
				while(true) {
					
					
					//(1)思考问题
					System.out.println("哲学家"+no+"正在思考问题...");
					//吃饭
					int left = no;
					int right = (no+1)%forks.getForkCount();
					
					//如果右叉子编号大于左叉子编号,交换顺序 
					if(right > left) {
						int temp = left;
						left = right;
						right = temp;
					}
			/*
			 * try { PhilosopherProblem.MUTEX.acquire(); } catch (InterruptedException e) {
			 * // TODO Auto-generated catch block e.printStackTrace(); }
			 */
					//1.拿起左叉子
					forks.get(left);
					System.out.println("\t\t\t哲学家"+no+"拿起左叉子");
					
					//2.拿起右叉子
					forks.get(right);
					System.out.println("\t\t\t哲学家"+no+"拿起右叉子");
					
					//3.吃饭
					System.out.println("\t\t\t\t\t\t"+"哲学家"+no+"正在吃饭...");
					
					//4.放下左叉子
					forks.put(left);
					System.out.println("\t\t\t哲学家"+no+"放下左叉子");
					
					//5.放下右叉子
					forks.put(right);
					System.out.println("\t\t\t哲学家"+no+"放下右叉子");
					
					//PhilosopherProblem.MUTEX.release();
				}
			}
			
		}

配上测试结果图:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值