操作系统哲学家进餐问题

时间:2024.4.14

         

         操作系统实习

      报告

一、设计目的:
      死锁是进程并发执行过程中可能出现的现象,所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局。哲学家就餐问题是描述死锁的经典例子。为了防止死锁,可以采用资源预分配法或者资源按序分配法。资源预分配法是指进程在运行前一次性地向系统申请它所需要的全部资源,如果系统当前不能够满足进程的全部资源请求,则不分配资源, 此进程暂不投入运行,如果系统当前能够满足进程的全部资源请求, 则一次性地将所申请的资源全部分配给申请进程。

二、设计内容

    哲学家进餐问题的模拟。

三、开发环境

windows环境,Myeclipse平台。

四、分析设计

<一>实验原理

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

由于:①只有拿到两只筷子时,哲学家才能吃饭;②如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;③任何一个哲学家在自己没有拿到两只筷子吃饭之前,决不放下自己手中的筷子。则可能出现五个哲学家都饥饿时都拿着一直筷子。这样就可能五个哲学家都用不上餐。

该问题可用记录型信号量解决,经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用,为了实现对筷子的互斥使用,可以用一个信号量表示一只筷子,由这五个信号量组成信号量数组。当哲学家饥饿时总是先拿其左边的筷子,成功后,再去拿右边的筷子,又成功后方可就餐。进餐完,又先放下他左边的筷子,再放下右边筷子。这个算法可以保证不会有两个相邻的哲学家同时就餐,但有可能引起死锁。

对于死锁问题可采取这样的几种解决方法:

(1)至多只允许四个哲学家同时进餐,以保证至少有一个哲学家可以进餐,最终总会释放出他所用过的两只筷子,从而可使更多的哲学家进餐;

(2)仅当左右两只筷子均可用时,才允许哲学家拿起筷子就餐

(3)规定奇数号哲学家先拿起右边筷子,然后再去拿左边筷子,而偶数号哲学家则相反。

(4)把筷子顺序编号 0, 1, 2, 3, 4,给每个哲学家分配筷子时,必须依从小号到大号(或者相反顺序)进行。

在本次实习里采用第二种方法解决该问题。

<二>数据及程序结构

     总共创建有四个类:哲学家进餐问题类,Philosopher类,ChopstickArray

类,Chopstick类。

Chopstick类来表示筷子,其中包括的布尔型成员变量available来表示该筷子是否可用,成员方法setnum()获取其编号;boolean型成员方法isAvailable()返回其当前available的值。setAvailable(boolean available)这一成员方法是对筷子的available的值进行设置,即设置筷子是否可用。

ChopstickArray类用其中的数组chopsticks[i]来存放五只筷子,并通过哲学家的编号及筷子的编号确定该筷子属于当前哲学家的左右哪边的筷子。

Philosopher类,用来描述哲学家,通过实现Runnable接口的方式来创建线程对象,该类中的方法thinking(),eating()来描述哲学家的状态。通过使用关键词synchronized来给共享资源即Philosopher对象上锁,当一个线问程访问Philosopher中的Thinking()时锁定Philosopher对象,这时其他线程就无法访问其另一个方法eating(),即说明哲学家不能同时处于思考和吃饭的状态中。

    publicsynchronizedvoid thinking()

    {

        if(state)        /* 如果在思考,说明这个哲学家两边的筷子没用 */

        {

            chopstickArray.getnum(num).setAvailable(true);

            chopstickArray.getLast(num).setAvailable(true);   /*这时哲学家两边的筷子只为可用*/

            String text = thinkingTextArea.getText();

            thinkingTextArea.setText(text+this + " 在思考\n");

            try

            {                    

              Thread.sleep(10000);                                              

            }catch(Exception e)

            {

                e.printStackTrace();

            }

        }

        state = false;               /*思考完成,进入饥饿状态*/

publicsynchronizedvoid eating()

    {

        if(!state)                                       /*  若不在在思考*/

        {

            if(chopstickArray.getnum(num).isAvailable()) /* 若哲学家右手边的筷子可用*/

            {         

              if(chopstickArray.getLast(num).isAvailable())/*如果左手边的筷子也可用,该哲学家状态设为在吃饭,其两侧的筷子都设置为不可用 */

              {                                                              

                    chopstickArray.getnum(num).setAvailable(false);

                    chopstickArray.getLast(num).setAvailable(false);

                    String text = eatingTextArea.getText();

                    eatingTextArea.setText(text+this + " 在吃饭\n");

                    try

                    {

                        Thread.sleep(10000);                                    

                    }catch(Exception e)

                    {

                        e.printStackTrace();

                    }

                }else

                {          /* 右手边的筷子可用,但是左手边的不可用*/

                  String str = waitingTextArea.getText();                                                

                  waitingTextArea.setText(str+this+" 等待左手边 "+chopstickArray.getLast(num)+"\n");

                    try

                    {

                        wait(new Random().nextInt(100));                

                    }catch(Exception e)

                    {

                        e.printStackTrace();

                    }

                }

            }else

            {               /* 如果哲学家右手边的筷子不可用则等待*/

                String str = waitingTextArea.getText();

                waitingTextArea.setText(str+this+" 等待右手边 "+chopstickArray.getnum(num)+"\n");

                try

                {

                    wait(new Random().nextInt(100));

                }catch(Exception e)

                {

                    e.printStackTrace();

                }

            }

        }

        state = true;

哲学家进餐问题类建立一个小程序界面。通过一个“程序开始”的按钮,创建出“筷子”和“哲学家”:

publicvoid actionPerformed(ActionEvent e)

{

   if(e.getActionCommand().equals("程序开始"))

   {

ChopstickArray chopstickArray = new ChopstickArray(5);                  

                                        /*五只“筷子”*/

for(int i = 0; i < 5; i++)

        {

         new Thread(newPhilosopher(i,chopstickArray,

thinkingTextArea,eatingTextArea, waitingTextArea)).start();      /*创建五个哲学家线程*/

            }

      }

  }

.运行示例及结果分析

首先哲学家0竞争到筷子进入吃饭状态,此时哲学家1和哲学家4无法获得足够筷子,而哲学家3左右筷子可用进入了吃饭状态,此时筷子4、筷子0、筷子2和筷子3不可用。而这时由思考到饥饿的哲学家1和哲学家4只好进入等待状态。

接下来哲学家0和哲学家3吃完饭其左右筷子进入思考,此时哲学家2饥饿竞争到了起左右筷子进入吃饭状态,饿了的哲学家1只好又等待,此时哲学家4左右筷子可用则进入吃饭状态,没等到筷子的哲学家1只好回去继续思考。

六、心得与体会

本次操作系统实习主要对操作系统一些功能块进行了了解,并通过自己设计小型操作系统模块使得我们对操作系统的了解更加深入。实习中还有对LINUX操作系统内核代码的分析,使我们具体的认识了LINUX,了解其设计思想和功能模块,而在LINUX下的各种常用命令也要求我们熟练掌握。通过实习让我们掌握了更多更详细的操作系统的知识,而且通过自己动手模拟演示其功能,体验操作系统的具体执行。而在编写小程序的时候,在同学们和老师的帮助下解决的了很多的困难。而其中对于多线程的编程对于解决并发性问题高效性也在实习中有了深刻的了解。在实习中我不仅学到了很多的知识,还通过查找解决问题的方法认识到解决问题有时需要不仅是一个人的力量,而是一个整体的力量。这些在我们今天的学习工作生活中是很重要的。最后还要多加感谢实习中同学们和老师的提供帮助。

源程序清单:                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     

import java.applet.*;

import java.awt.event.*;

import java.awt.*;

import java.util.Random;

public  class哲学家进餐问题extends Applet implements ActionListener,TextListener

{

    private Button But1;   

    TextArea thinkingTextArea,eatingTextArea,waitingTextArea;

    publicvoid init()

    {

        But1 =new Button("程序开始");      

        But1.addActionListener(this);

        add(But1);

       

        thinkingTextArea = new TextArea("思考中:\n",30, 20);

        add(thinkingTextArea);

        eatingTextArea = new TextArea("吃饭中:\n",30, 20);

        add(eatingTextArea);

        waitingTextArea = new TextArea("等待中:\n",30, 28);

        add(waitingTextArea);

    }

   

    publicvoid actionPerformed(ActionEvent e)

    {

       if(e.getActionCommand().equals("程序开始"))

       {

           ChopstickArray chopstickArray = new ChopstickArray(5);

            for(int i = 0; i < 5; i++)

            {

                new Thread(new Philosopher(i,chopstickArray,thinkingTextArea,eatingTextArea, waitingTextArea)).start();

            }

       }

    }

    publicstaticvoid main(String[] args)

    {

        new 哲学家进餐问题();

    }

    publicvoid textValueChanged(TextEvent e)

    {

       // TODO Auto-generated method stub

    }

}

 class Philosopher implements Runnable    /*哲学家类*/

{

    public Philosopher(int num, ChopstickArray chopstickArray,TextArea thinkingTextArea, TextArea eatingtextArea, TextArea waitingTextArea)

    {

        this.num = num;

        this.chopstickArray = chopstickArray;

        this.thinkingTextArea = thinkingTextArea;

        this.eatingTextArea = eatingtextArea;

        this.waitingTextArea = waitingTextArea;

    }

    publicsynchronizedvoid thinking()

    {

        if(state)        /* 如果在思考,说明这个哲学家两边的筷子没用 */

        {

            chopstickArray.getnum(num).setAvailable(true);

            chopstickArray.getLast(num).setAvailable(true);

            String text = thinkingTextArea.getText();

            thinkingTextArea.setText(text+this + " 在思考\n");

            try

            {                     

              Thread.sleep(10000);                                                  

            }catch(Exception e)

            {

                e.printStackTrace();

            }

        }

        state = false;

    }

    publicsynchronizedvoid eating()

    {

        if(!state)                                       /*  若不在在思考*/

        {

            if(chopstickArray.getnum(num).isAvailable()) /* 若哲学家右手边的筷子可用*/

            {         

              if(chopstickArray.getLast(num).isAvailable())/*如果左手边的筷子也可用,该哲学家状态设为在吃饭,其两侧的筷子都设置为不可用 */

              {                                                              

                    chopstickArray.getnum(num).setAvailable(false);

                    chopstickArray.getLast(num).setAvailable(false);

                    String text = eatingTextArea.getText();

                    eatingTextArea.setText(text+this + " 在吃饭\n");

                    try

                    {

                        Thread.sleep(10000);                                    

                    }catch(Exception e)

                    {

                        e.printStackTrace();

                    }

                }else

                {                             /* 右手边的筷子可用,但是左手边的不可用*/

                    String str = waitingTextArea.getText();                                               

                    waitingTextArea.setText(str+this+" 等待左手边 "+chopstickArray.getLast(num)+"\n");

                    try

                    {

                        wait(new Random().nextInt(100));

                    }catch(Exception e)

                    {

                        e.printStackTrace();

                    }

                }

            }else

            {               /* 如果哲学家右手边的筷子不可用则等待*/

                String str = waitingTextArea.getText();

                waitingTextArea.setText(str+this+" 等待右手边 "+chopstickArray.getnum(num)+"\n");

                try

                {

                    wait(new Random().nextInt(100));

                }catch(Exception e)

                {

                    e.printStackTrace();

                }

            }

        }

        state = true;

    }

    publicvoid run()

    {

        for(int i = 0; i < 10; ++i)

        {

            thinking();

            eating();

        }

    }

    public String toString()

    {

        return " 哲学家 " + num;

    }

    privateint num;

    privateboolean state;

    ChopstickArray chopstickArray;

    TextArea thinkingTextArea;

    TextArea eatingTextArea;

    TextArea waitingTextArea;

}

 class ChopstickArray         /*      存放筷子类的数组            */

{

        public ChopstickArray(int size)

       {

        chopsticks = new Chopstick[size];

        for(int i = 0; i < chopsticks.length; ++i)

        {

            chopsticks[i] = new Chopstick(i);

        }

       }

 

    public Chopstick getnum(int num)     

    {

        return chopsticks[num];

    }

    public Chopstick getLast(int num)

        {

        if(num==0)

          {

            return chopsticks[chopsticks.length-1];

          }else

          {

            return chopsticks[num-1];

          }

        }

    private Chopstick[] chopsticks;

}

  class Chopstick         /*筷子的类 */

{

    public Chopstick(int num)

    {

       this.num = num;

    }

    publicboolean isAvailable()

    {

      return available;

    }

    publicvoid setAvailable(boolean available)

    {

      this.available = available;

    }

    publicint getnum()

    {

        return num;

    }

    publicvoid setnum(int num)

    {

        this.num = num;

    }

    public String toString()           

    {

        return "筷子" + num;                      

    } 

    privatevolatileboolean available = true;         /*   表示筷子是否可用        */

    privateint num;

}

更多相关推荐:
哲学家就餐问题

哲学家进餐问题的研究计算机操作系统姓名陆文静学号1310750012指导老师杨婷婷专业班级软件工程1301班完成时间20xx年5月4日哲学家进餐问题研究摘要一问题的描述哲学家就餐问题是一种典型的同步问题它是由D...

哲学家就餐问题华科 操作系统

操作系统实验报告实验名称哲学家就餐问题院系电子与信息工程系班级通信1004学号U20xx13086姓名张建佳20xx620一实验目的1读懂mfc编写的科学家就餐程序对C语言加深理解2理解哲学家就餐问题中出现的问...

哲学家就餐问题

数学与计算机学院课程设计说明书课程名称:操作系统原理-课程设计课程代码:8404061题目:哲学家就餐问题模拟年级/专业/班:09级信息与计算科学三班学生姓名:**学号:***开始时间:20**年05月14日完…

哲学家就餐问题

哲学家问题解决方法探析摘要本文讨论了操作系统里关于同步哲学家就餐问题的两种解法哲学家就餐问题是一种典型的同步问题它是由Dijkstra提出并解决的哲学家就餐问题是从计算机实现伪同步并行功能研究中演化而来的经典进...

哲学家就餐问题

实验一一实验名称哲学家就餐问题的实现二实验学时2三实验内容和目的实验目的实现哲学家就餐问题要求不能出现死锁通过本实验熟悉Linux系统的基本环境了解Linux下进程和线程的实现实验内容在Unix系统下实现教材2...

哲学家就餐问题解释

哲学家就餐问题是在计算机科学中的一个经典问题用来演示在并行计算中多线程同步Synchronization时产生的问题在19xx年著名的计算机科学家艾兹格迪科斯彻提出了一个同步问题即假设有五台计算机都试图访问五份...

哲学家就餐问题

20xx20xx学年第二学期重庆理工大学研究生课程论文课程论文题目基于ucosii操作系统解决哲学家就餐问题ProblemofPhilosophersDining课程名称课程类别任课教师所在学院学科专业姓学名号...

哲学家就餐问题代码2

includeltiostreamgtincludeltiomanipgtincludeltctimegtincludeltcstdlibgtusingnamespacestdenumStateTHINKWAI...

哲学家就餐及理发师问题

1哲学家进餐问题1在什么情况下5个哲学家全部吃不上饭考虑两种实现的方式如下A算法描述voidphilosopherintii哲学家编号从0到4whileTRUEthink哲学家正在思考takeforki取左侧的...

哲学家就餐问题代码

includeltstdiohgtincludeltstdlibhgtincludeltstringhgtincludeltpthreadhgtincludeltsemaphorehgtincludeltsys...

哲学家就餐问题代码

includeltstdiohgtincludeltstdlibhgtincludeltstringhgtincludeltpthreadhgtincludeltsemaphorehgtincludeltsys...

哲学家就餐问题

淮北师范大学课程设计报告哲学家就餐问题学院专业学号学生姓名指导教师姓名20xx年3月14日1实验目的与设计要求实验目的通过实现哲学家进餐问题的同步深入了解和掌握进程同步和互斥的原理设计要求哲学家有N个也定全体到...

哲学家就餐问题总结(23篇)