哲学家就餐问题(进程管理)

2019-09-01 22:39

操作系统实验报告

进程管理

一、 设计目的、功能与要求

设计目的:掌握进程管理的相关内容,对进程的同步和互斥,及信号量机制有深入的理解

实验内容:模拟实现用信号量机制解决哲学家就餐问题 具体要求:

? 任选一种计算机高级语言编程实现 ? 实现5个哲学家(5只筷子)的顺利就餐 ? 需避免出现死锁

? 使用信号量、及信号量的等待队列 ? 使用P操作、V操作

? 能够显示每个哲学家、及每只筷子的状态

二、 问题的详细描述、需求分析

该实验要求模拟实现用信号量机制解决哲学家就餐问题。 哲学家就餐问题详细描述如下:

有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子,即共5只筷子。每个哲学家的行为是思考和进餐。每个哲学家的行为是思考和进餐。为了进餐,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子。思考时则同时将两支筷子放回原处时则同时将两支筷子放回原处。

规则:只有拿到两只筷子时,哲学家才能吃饭;只有拿到两只筷子时,哲学家才能吃饭;如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;任何一个哲学家在自己没有拿到两只筷子吃饭之前,决不放下自己手中的筷子。

1/ 6

操作系统实验报告

为了解决哲学家就餐问题同时解决死锁现象,需要设计一定的解决策略。有这样几种解决办法:

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

2.仅当左右两只筷子均可用时,才允许哲学家拿起筷子就餐; 3.规定奇数号哲学家先拿起右边筷子,然后再去拿左边筷子,而偶数号哲学家则相反。

该实验我采取了第2种解决方案,每个哲学家在确定自己左右两边的筷子都能用时,才能同时拿起两只筷子进餐,进餐完成后同时放下两只筷子。

三、 数据结构、功能设计(功能与框图、功能模块说明)

该实验使用java的多线程,同时利用到关键字synchronized实现了共享数据的互斥锁定,以保证每只筷子的状态的互斥的。在Philosopher的构造函数里面,用super()调用父类的构造函数,以此创建一个线程。在run()方法里面写入每个哲学家的状态变化情况,最终用start()方法实现多进程,解决哲学家就餐问题。

整个程序在一个包里面有三个类,分别为哲学家Philosopher类、筷子Chopstick类和测试Test类。其中Philosopher类继承了Thread类实现线程。筷子类Chopstick中有takeChopstick()函数和putChopstick()函数,分别处理每个哲学家同时拿起和放下左右两边的筷子。筷子类Chopstick中有一个布尔型数组用来存储每只筷子的状态,起始状态都为false,即没有被拿起来使用。在takeChopstick()函数和putChopstick()函数中改变筷子的状态,同时在控制台打印输出筷子此时的状态。Test类中建立五个线程并都用start()方法启动。

四、 开发工具及源程序的主要部分(需对主要代码段附文字注释)

IDE:eclipse 源码如下: Philosopher类:

package package1;

publicclass Philosopher extends Thread {

2/ 6

高级语言:Java

操作系统实验报告

private String ID; //哲学家编号

privateChopStickchopstick; //创建一个筷子对象 public Philosopher(String ID,ChopStickchopstick){ super(ID); //调用父类的构造函数 this.ID=ID;

this.chopstick=chopstick; }

publicvoid run(){ while(true){

thinking(); //哲学家正在思考

chopstick.takeChopstick(); //哲学家同时拿起了左右筷子 eating(); //哲学家正在吃饭 chopstick.putChopstick(); //哲学家放下了左右筷子 }

}

publicvoid eating(){

System.out.println(ID+\号哲学家正在吃饭\); try {

sleep(1000);//模拟吃饭,占用一段时间资源 } catch (InterruptedExceptione) { e.printStackTrace(); } }

publicvoid thinking(){

System.out.println(ID+\号哲学家正在思考\); try {

sleep(1000);//模拟思考,占用一段时间资源 } catch (InterruptedExceptione) { e.printStackTrace(); } }

}

Chopstick类:

publicclassChopStick {

privateboolean[] used={false,false,false,false,false}; //筷子的初始状态都是未被拿起

publicsynchronizedvoidtakeChopstick()

3/ 6

操作系统实验报告

//用synchronized将该方法锁定到一个线程上 {

String ID = Thread.currentThread().getName(); inti = Integer.parseInt(ID); while(used[i]||used[(i+1)%5]){ try {

wait();//如果左右手有一只正被使用,等待 } catch (InterruptedExceptione) { e.printStackTrace(); } }

used[i]= true;

System.out.print(i+\号筷子被拿起来了,\); used[(i+1)%5]=true;

System.out.println((i+1)%5+\号筷子被拿起来了\); }

publicsynchronizedvoidputChopstick(){

String ID = Thread.currentThread().getName(); inti = Integer.parseInt(ID); used[i]= false;

System.out.print(i+\号筷子被放下了,\); used[(i+1)%5]=false;

System.out.println((i+1)%5+\号筷子被放下了\); notifyAll();//唤醒其他线程 } }

Test类:

publicclass Test {

publicstaticvoid main(String []args){

ChopStickchopstick = newChopStick(); //新建筷子对象 new Philosopher(\,chopstick).start(); //启动各个线程 new Philosopher(\,chopstick).start(); new Philosopher(\,chopstick).start(); new Philosopher(\,chopstick).start(); new Philosopher(\,chopstick).start(); }

}

五、 测试用例、运行结果与运行情况分析

运行结果如图所示:

4/ 6

操作系统实验报告

哲学家可以多次就餐,多次进入休息或等待状态,若不暂停程序,则进程会一直继续下去。在控制台,打印了每个哲学家的状态变化和每只筷子的状态变化。

六、 自我评价与总结

该次实验由于要解决哲学家就餐问题,有对进程的同步和互斥操作,于是首先想到的是采用多线程的方法解决。而Java语言对多线程的操作比较方便,于是选择了Java作为编程语言。由于学Java时对多线程比较陌生,没有深入学习,于是在实验的准备阶段,我首先把Java教材多线程部分学习了一遍,同时利用强大的网络平台搜索了Java多线程方面的知识。在学会了Java多线程的知识后,我便将哲学家问题抽象化,首先理顺了思路,然后考虑了用类来封装,在类中实现每个对象的方法。

5/ 6

操作系统实验报告

实验过程中遇到了很多问题,我也参考了网络上的解决办法,并且查阅了很多解决哲学家就餐问题的具体方案和实现代码,在学习过程中,我一步一步解决了自己编程的错误。最后,能够顺利解决哲学家就餐问题。但是,我的实验代码不能很好地控制哲学家就餐的次数,只能通过人为控制程序中断,来观察哲学家们的状态变化和筷子的状态变化,这点仍然需要改进。

总之,本次实验收获很大,既深入学习了Java多线程,又掌握了进程管理的相关内容,对进程的同步和互斥,及信号量机制有深入的理解。

6/ 6


哲学家就餐问题(进程管理).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:宪章文本

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: