`
XD.zhang
  • 浏览: 11143 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

哲学家算法

 
阅读更多

哲学家算法

 

 

              操作系统中,为了避免互斥资源使用导致死锁 问题,有很多的解决方法,其中一种方法就是哲学家算法。

              首先说一下什么是哲学家算法,有5个哲学家,他们只会思考和吃饭,但是在一个圆形的桌子上面 只有5支筷子,些哲学家什么时候来吃东西是不确定的,也就是说,同一时间可能会有5个人来进食,也可能一个人也没有。 要想吃饭,必须有两双筷子,所以要约定一种取得筷子的方法。如果没有什么约束条件,可能出现下面的状况:

             1 假设哲学家吃饭的时候会首先取得自己左侧的筷子,可能在某一瞬间 5个人同时吃饭 同时拿起了左面的筷子,得不到另一支筷子时就放下了筷子并同时拿起了自己右侧的筷子,如此反复循环。。。导致程序无法向前运行。

             2、假设哲学家吃饭的时候首先拿取左侧的筷子,再检查右侧的筷子 如果右侧的筷子不用,则放下自己已经取得的筷子,过一段时间后在重复这一个过程。这个方法看似可行,仔细一想却和1中的情况差不多,可能在某一个瞬间,5个人同时启用这个方法,又会出现1中的情况。。。程序还是不会运行。

             为了避免出现这种情况,有了哲学家算法,其中一种方案是:

             1、3、5(奇数)号哲学家会分别先取离自己最近的奇数号筷子,然后再取离自己最近的右侧的筷 子,2、4(偶数)号则分别取右侧最近的奇数号筷子,再去竞争离自己最 的偶数号筷子 哲学家会先竞争奇数位上的筷子,再去竞争偶数位上的筷子,总有一个能吃上饭,且根据FIFO队列,其他等待的哲学家会依次得到筷子吃饭故,可以实现程序的正常运行。具体代码如下:

 

 

package Philosopher;

public class Semaphore {
	int count;//共享的资源数的数量。
	public Semaphore (int count){
		this.count=count;
	}
	//操作系统p操作
	public synchronized void P(){
		count--;
		if(count<0){//如果资源小于0,则加入等待队列中,为阻塞状态。
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	//操作系统v操作
	public synchronized void V(){
		count++;
		if(count<=0){//如果不大于0,则唤醒等待的线程。
			notify();
		}
	}
}

 

         上面出现的P操作和V操作是一组运行过程中不可停止的原始操作,属于计算机原语。具体知识见操作系统原理。

 

public class Philosopher extends Thread{
	
	private int n;
	
	public Philosopher(int n){
		this.n=n;
	}
	
	//重写run方法
	public void run(){
		/**
		 * 拿筷子的时候,约定:
		 * Philosopher编号为奇数的先取自己右边的筷子,编号为偶数的先取自己左边的筷子。
		 */
		while(true){
		if(n%2==0){
			System.out.println("Philosopher"+n+"尝试取得"+(n+1)%5+"支筷子 ");
			Starteat .chopsticks[(n+1)%5].P();
			System.out.println("Philosopher"+n+"已经取得"+(n+1)%5+"支筷子");
			System.out.println("Philosopher"+n+"尝试取得"+(n)%5+"支筷子");
			Starteat .chopsticks[(n)%5].P();
			System.out.println("Philosopher"+n+"已经取得"+(n)%5+"支筷子");
			System.out.println("Philosopher"+n+"正在吃饭中。。。。。。");
			try {
				Thread.sleep(1);//吃饭时间。。
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Starteat .chopsticks[(n+1)%5].V();
			Starteat .chopsticks[(n)%5].V();
			System.out.println("Philosopher"+n+"放下了第"+n+"和"+n+1);
			System.out.println("Philosopher"+n+"已经进食完毕。开始思考。。。。");
		}
		else {
			System.out.println("Philosopher"+n+"尝试取得"+(n)%5+"支筷子");
			Starteat .chopsticks[(n)%5].P();
			System.out.println("Philosopher"+n+"已经取得"+(n)%5+"支筷子");
			System.out.println("Philosopher"+n+"尝试取得"+(n+1)%5+"支筷子");
			Starteat .chopsticks[(n+1)%5].P();
			System.out.println("Philosopher"+n+"已经取得"+(n+1)%5+"支筷子");
			System.out.println("Philosopher"+n+"正在吃饭中。。。。。。");
			try {
				Thread.sleep(1);//吃饭时间。。
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			Starteat .chopsticks[(n+1)%5].V();
			Starteat .chopsticks[(n)%5].V();
			System.out.println("Philosopher"+n+"放下了第"+n+"和"+n+1);
			System.out.println("Philosopher"+n+"已经进食完毕。开始思考。。。。");
			}
		}
	}
}

                由于两个人之间是竞争一支筷子,所以semaphore设置为1.

package Philosopher;

public class Starteat {
	
	static Semaphore [] chopsticks = new Semaphore [5];
	
	public static void main(String [] agrs){
		
		for(int i=0;i<5;i++){
			chopsticks[i] = new Semaphore(1);
		}
		for(int i=0;i<5;i++){
			new Philosopher(i).start();
		}
	}
}
 

           代码实现起来比较容易,种方法只是哲学家算法中的一种,你也可以限制同时吃饭的人数(如最多只能允许4人同时吃饭 )来解决哲学家吃饭饿死的问题。只是效率会不同。本人水平有限,不足之处请大家多多包涵。

 

 

 

分享到:
评论

相关推荐

    哲学家算法的实现

    哲学家算法是操作系统设计中的一个经典问题,它模拟了五个哲学家围坐在一张圆桌边,每个人面前都有一根筷子。哲学家们交替地思考和吃饭,但若五个人同时拿起左右两边的筷子,就会陷入无法进食的死锁状态。为了解决这...

    演示操作系统中哲学家算法

    在这个C#实现的哲学家算法演示中,我们可以通过以下关键知识点来理解: 1. **并发控制**:哲学家就餐问题展示了在多线程环境中可能出现的并发问题,如死锁。在操作系统中,通过锁、信号量、条件变量等机制来协调...

    哲学家算法c++(操作系统实验)

    操作系统实验——哲学家算法c++ 参考一下吧

    哲学家算法-java

    哲学家算法,也被称为Dining Philosophers Problem,是计算机科学中的一个经典问题,它由艾兹格·迪科斯彻在1965年提出,用于揭示并发控制和死锁现象。在这个问题中,五位哲学家围坐在一张桌子旁,每人面前都有一根...

    操作系统课程设计 哲学家算法

    总体而言,操作系统课程设计,特别是哲学家算法这一模块,不仅要求学生掌握编程技能,还需要他们能够将理论知识应用于实际问题的解决中。通过这样的实践,学生不仅能够加深对操作系统核心概念的理解,而且能够提升...

    哲学家问题算法代码描述

    《哲学家问题算法代码解析》 ...然而,为了彻底解决哲学家问题,我们需要更高级的并发控制策略,如银行家算法或使用Java的`ReentrantLock`等工具。这为深入理解并发编程和死锁预防提供了宝贵的实践案例。

    关于哲学家进餐算法的演示

    在C++Builder中实现哲学家进餐算法,主要涉及到线程同步和互斥量(mutex)的概念。C++Builder提供了如`TThread`类和`CriticalSection`等工具来处理线程同步。以下是该问题的关键知识点: 1. **线程**: 在多线程环境...

    linux 下qt实现哲学家问题

    8. **并发控制策略**:解决哲学家问题有多种策略,如避免死锁的银行家算法、优先级逆置法等。在Qt实现中,我们可以选择最简单的“先取左边筷子再取右边”规则,这样可以保证不会出现环形等待,避免死锁。 通过以上...

    Linux下进程的哲学家进餐

    在操作系统的世界里,"哲学家进餐问题"是一个经典的多线程或进程同步问题,它由计算机科学家Edsger Dijkstra提出,用以演示资源竞争可能导致的死锁现象。在这个问题中,五个哲学家围坐在一张圆桌旁,每个人面前都有...

    哲学家就餐问题课题设计与思考

    7. **哲学家算法**: - 每个哲学家的动作包括思考、饥饿、取筷子、进食和放筷子。 - 五个哲学家的并发动作需要通过多线程和信号量协调,以确保不会出现死锁和饿死。 8. **并发控制**: - 在实现中,需要测试哲学...

    哲学家就餐问题算法分析与代码

    哲学家就餐问题的分析与代码,供大家参考吧,很详细

    操作系统 哲学家进餐进程算法

    实验一 进程同步互斥——不死锁的哲学家问题  (1)输入的形式和输入值的范围;  由于这个是一个按钮实现监控,界面提供视图的程序,所以并不需要别的附加的输入,只需要点击相应的按钮即可。按钮有开始、暂停、结束...

    哲学家进餐问题 算法 vc源代码 测试通过

    经典算法解决哲学家进餐问题通常有两种策略:避免死锁和预防死锁。 1. **避免死锁**: 这种策略是在每次哲学家试图拿起筷子时检查是否会导致死锁。例如,可以使用一个循环等待图来表示当前状态,如果不存在形成...

    操作系统的几个经典算法

    解决方法包括使用信号量、银行家算法等,确保资源分配策略能防止死锁,并保证所有哲学家都能公平地获得食物。 3. **生产者-消费者问题**: 在这个经典的并发问题中,生产者生成产品并放入缓冲区,而消费者从缓冲区...

    哲学家就餐算法

    哲学家就餐算法是计算机科学中一个经典的问题,它源自图灵奖得主Edsger Dijkstra提出的一个模拟并发问题,旨在探讨多线程环境下的死锁预防策略。在这个问题中,有五个哲学家围坐在一张圆桌旁,每个人面前都有一根...

    哲学家就餐问题算法 进行哲学家拿筷子过程

    ### 哲学家就餐问题详解 #### 一、问题背景及定义 哲学家就餐问题是并发控制领域中的一个经典问题,通常被用来说明进程同步中死锁的问题。该问题描述为:有五位哲学家围坐在一张圆桌旁,每个人面前有一只筷子(共...

    C#哲学家进餐算法

    《C#实现哲学家进餐算法详解》 在软件工程领域,模拟问题并寻找解决方案是常见的一种编程训练。"哲学家进餐问题"(Dining Philosophers Problem)就是这样一个经典的多线程同步问题,它源自计算机科学家Edsger ...

Global site tag (gtag.js) - Google Analytics