当前位置:文档之家› 操作系统课程设计利用多线程和信号量解决哲学家进餐问题 java实现

操作系统课程设计利用多线程和信号量解决哲学家进餐问题 java实现

操作系统课程设计利用多线程和信号量解决哲学家进餐问题 java实现
操作系统课程设计利用多线程和信号量解决哲学家进餐问题 java实现

操作系统课程设计

课程设计报告

课题:利用信号量和多线程机制实现“哲学家进餐”问题

所在学院:信息工程学院

班级:计科1201

学号:121404114

姓名:魏祥

指导教师:徐向英

2015年1月1日

目录

一、课程设计目标 (3)

二、课题内容 (3)

三、设计思路 (3)

四、源代码 (5)

五、运行与测试 (9)

六、心得体会 (10)

一、课程设计目标

学习多线程编程,使用线程的同步机制实现“哲学家进餐”问题。具体要求:1.创建POSIX线程,实现多线程的并发执行,验证多线程共享进程资源的特性。

2.使用互斥量和条件变量,或使用信号量实现线程的同步互斥。

3. 验证“ 哲学家进餐”问题中的死锁情况,并加以解决。

二、课题内容

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

本次课题要求使用多线程和信号量解决哲学家进餐问题。并演示产生死锁的情况。

三、设计思路

经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许以为哲学家使用。为了实现对筷子的互斥,可以用一个信号量表示一只筷子,由着五个信号量构成信号量数组。

当哲学家饥饿时总是先去拿左筷子,成功后在拿右筷子。当五位哲学家同时拿起左筷子,这是每位哲学家都没有右筷子可以拿,就会造成死锁。

思路1:利用记录型信号量

设置值为4的记录型信号量,至多只允许四位哲学家同时去拿左筷子(leftStick.getSema().acquire()),只有拿到左筷子,才能继续拿右筷子(rightStick.getSema().acquire())。拿到两双筷子之后便可以用餐,用餐完毕,先放下左筷子(leftStick.getSema().release()),再放下右筷子(rightStick.getSema().release())。这样便可以避免思索问题。

思路2:利用AND型信号量

要求每个哲学家必须获取两个筷子的时候才能够进餐,只得到一只筷子不能进餐时,要求释放那一只筷子。可以使用AND型信号量将左筷子和右筷子信号量的获取组成一个原子操作。如此也可以避免死锁问题。

本次课程设计是在windows系统下完成,编程语言为java,开发环境:Eclipse。

由于在java语言中使用记录型信号量更为方便,所以本次课题我使用的是思路一。

这两行注释掉,取消至多只允许四位哲学家一起拿起左筷子的限制,就会产生死锁。

四、源代码

//在Windows下运行,

筷子类(ChopStick.java)

import java.util.concurrent.Semaphore;

public class ChopStick {

private int ID;

private boolean available;

private Semaphore semaphore = new Semaphore(1);

public ChopStick(int ID){

this.ID = ID;

this.available = true;

this.semaphore = new Semaphore(1);

}

public void setAvai(boolean available){

this.available = available;

}

public boolean getAvai(){

return this.available;

}

public Semaphore getSema(){

return this.semaphore;

}

public void setSema(Semaphore sema){

this.semaphore = sema;

}

public int getId(){

return this.ID;

}

}

哲学家类(Philosopher.java)

import java.util.concurrent.Semaphore;

public class Philosopher implements Runnable{

private int ID;

static Semaphore room = new Semaphore(4);

private ChopStick leftStick;

private ChopStick rightStick;

public Philosopher(int ID, ChopStick cs1, ChopStick cs2){

this.ID = ID;

this.leftStick = cs1;

this.rightStick = cs2;

}

public void getLeftChopStick(){

this.leftStick.setAvai(false);

}

public int getId(){

return ID;

}

public void eat(){

leftStick.setAvai(false);

rightStick.setAvai(false);

System.out.println("哲学家"+ this.getId() + "正在用餐。。。");

}

public void think(){

System.out.println("哲学家" + this.getId() + "正在思考。。。");

}

public void finishEat(){

System.out.println("哲学家" + this.getId() + "用餐结束,正在思考。。。");

leftStick.setAvai(true);

rightStick.setAvai(true);

}

public void readyToEat(){

System.out.println("哲学家" + this.getId() + "饿了准备用餐。。。");

}

public void cannotEat(){

System.out.println("哲学家" + this.getId() + "缺少筷子,不能用餐,等待。。。");

}

public void run(){

try{

room.acquire();

this.readyToEat();

if(this.leftStick.getSema().availablePermits() == 0 ||

this.leftStick.getSema().availablePermits() == 0){

this.cannotEat();

}

this.leftStick.getSema().acquire();

Thread.sleep(1000 * 1);

this.rightStick.getSema().acquire();

this.eat();

Thread.sleep(1000 * 2);

this.finishEat();

this.leftStick.getSema().release();

this.rightStick.getSema().release();

room.release();

}catch(InterruptedException ex){

ex.toString();

}

}

}

测试(Test.java)

import java.util.concurrent.*;

import java.util.Scanner;

public class Test {

public static void main(String[] args){

Scanner input = new Scanner(System.in);

menu();

int choice = input.nextInt();

while(choice != 1){

if(choice == 0){

ChopStick[] chopStick = new ChopStick[5];

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

chopStick[i] = new ChopStick(i);

}

ExecutorService excutor = Executors.newFixedThreadPool(5);

Philosopher ph0 = new Philosopher(0, chopStick[0], chopStick[1]);

excutor.execute(new Philosopher(0, chopStick[0], chopStick[1]));

excutor.execute(new Philosopher(1, chopStick[1], chopStick[2]));

excutor.execute(new Philosopher(2, chopStick[2], chopStick[3]));

excutor.execute(new Philosopher(3, chopStick[3], chopStick[4]));

excutor.execute(new Philosopher(4, chopStick[4], chopStick[0]));

excutor.shutdown();

}

choice = input.nextInt();

menu();

}

}

public static void menu(){

System.out.println("0: 演示");

System.out.println("1: 结束");

}

}

五、运行与测试

1.运行界面

2.死锁演示

3.无死锁演示

六、心得体会

本次课程设计我总得来说花的时间不是太多,代码加起来一共不超过两百行。我只用了一种思路来完成。思路一完成之后,我也尝试着用思路二完成,但是AND型信号量的问题很难解决,最后便放弃了。拿到课题之前我对哲学家进餐问题了解的还不是很透彻,我利用网络和查询课本彻底搞懂了哲学家进餐问题。并且得到两种解决思路。通过此次的课程设计,我想我对多线程的编程理解更深了一点,虽然说死锁的出现几率不是非常的大,但是还是有可能会出现,一旦出现,程序就会锁在哪里,不能继续执行。所以解决死锁是非常必要的。

由于我在学习java语言的时候,里面有专门降到多线程编程,这对我顺利的完成此次的课程设计有很大的帮助。Jdk里面丰富的类库也省去了我编写线程类和信号量类的功夫。虽然说不必考虑这些,但编写代码的时候我还是遇到了一些问题,多线程的执行和信号量的设置让我话费了一些时间。

总的说,这次课程设计,我只用了一种法案解决了哲学家进餐问题,这让我有点不满意。但独自完成课程设计的感觉还是很畅快的。也让我对多线程,信号量的理解更深了。

哲学家就餐问题代码

#include #include #include #include #include #include #include #include #include #define NUM_THREADS_P 5 /*define the number of philosopher*/ #define CHAIR_NUM 4 #define CHOP_NUM 5 int chairflg[CHAIR_NUM][2],dining_num=0; sem_t chair,chopsticks[CHOP_NUM],mutex,mutex1,print_mutex;// 设定信号量pthread_t threads_p[NUM_THREADS_P]; /*philosopher*/ void* philosopher_thread(int tid); int main(){ int i; sem_init(&chair,0,CHAIR_NUM); /*set the value of semaphores*/ for(i=0;i

java线程练习题及答案

线程与线程类 1 线程的概念 线程的概念来源于计算机的操作系统的进程的概念。进程是一个程序关于某个数据集的一次运行。也就是说,进程是运行中的程序,是程序的一次运行活动。 线程和进程的相似之处在于,线程和运行的程序都是单个顺序控制流。有些教材将线程称为轻量级进程(light weight process)。线程被看作是轻量级进程是因为它运行在一个程序的上下文内,并利用分配给程序的资源和环境。 作为单个顺序控制流,线程必须在运行的程序中得到自己运行的资源,如必须有自己的执行栈和程序计数器。线程内运行的代码只能在该上下文内。因此还有些教程将执行上下文(execution context)作为线程的同义词。 所有的程序员都熟悉顺序程序的编写,如我们编写的名称排序和求素数的程序就是顺序程序。顺序程序都有开始、执行序列和结束,在程序执行的任何时刻,只有一个执行点。线程(thread )则是进程中的一个单个的顺序控制流。单线程的概念很简单,如图1所示。 多线程(multi-thread )是指在单个的程序内可以同时运行多个不同的线程完成不同的任务,图2说明了一个程序中同时有两个线程运行。 图1 单线程程序示意图 图2 多线程程序示意图 有些程序中需要多个控制流并行执行。例如, for(int i = 0; i < 100; i++) System.out.println("Runner A = " + i); for(int j = 0; j < 100; j++ ) System.out.println("Runner B = "+j); 上面的代码段中,在只支持单线程的语言中,前一个循环不执行完不可能执行第二个循环。要使两个循环同时执行,需要编写多线程的程序。 很多应用程序是用多线程实现的,如Hot Java Web 浏览器就是多线程应用的例子。在Hot Java 浏览器中,你可以一边滚动屏幕,一边下载Applet 或图像,可以同时播放动画和声音等。 2 Thread 类和Runnable 接口 多线程是一个程序中可以有多段代码同时运行,那么这些代码写在哪里,如何创建线程对象呢? 首先,我们来看Java 语言实现多线程编程的类和接口。在https://www.doczj.com/doc/1b17042922.html,ng 包中定义了Runnable 接口和Thread 类。

Java第七单元练习题-Java多线程机制

7Java多线程机制 7.1单项选择题 1. 线程调用了sleep()方法后,该线程将进入()状态。 A. 可运行状态 B. 运行状态 C. 阻塞状态 D. 终止状态 2. 关于java线程,下面说法错误的是() A. 线程是以CPU为主体的行为 B. java利用线程使整个系统成为异步 C. 创建线程的方法有两种:实现Runnable接口和继承Thread类 D. 新线程一旦被创建,它将自动开始运行 3. 在java中的线程模型包含() A. 一个虚拟处理器 B. CPU执行的代码 C. 代码操作的数据 D. 以上都是 4.在java语言中,临界区可以是一个语句块,或者是一个方法,并用()关键字标识。 A. synchronized B. include C. import D. Thread 5. 线程控制方法中,yield()的作用是() A. 返回当前线程的引用 B. 使比其低的优先级线程执行 C. 强行终止线程 D. 只让给同优先级线程运行 6. 线程同步中,对象的锁在()情况下持有线程返回 A. 当synchronized()语句块执行完后 B. 当在synchronized()语句块执行中出现例外(exception)时 C. 当持有锁的线程调用该对象的wait()方法时 D. 以上都是 7. 在以下()情况下,线程就进入可运行状态 A. 线程调用了sleep()方法时 B. 线程调用了join()方法时

C. 线程调用了yield()方法时 D. 以上都是 8. java用()机制实现了进程之间的异步执行 A. 监视器 B. 虚拟机 C. 多个CPU D. 异步调用 类的方法中,toString()方法的作用是() A. 只返回线程的名称 B. 返回当前线程所属的线程组的名称 C. 返回当前线程对象 D. 返回线程的名称 语言具有许多优点和特点,下列选项中,哪个反映了Java程序并行机制的特点() A. 安全性 B. 多线程 C. 跨平台 D. 可移值 11.以下哪个关键字可以用来对对象加互斥锁?() A. transient B. synchronized C. serialize D. static 12.下面关于进程、线程的说法不正确的是( )。 A.进程是程序的一次动态执行过程。一个进程在其执行过程中,可以产生多个线程——多线程,形成多条执行线索。 B.线程是比进程更小的执行单位,是在一个进程中独立的控制流,即程序内部的控制流。线程本身不能自动运行,栖身于某个进程之中,由进程启动执行。 C.Java多线程的运行与平台无关。 D.对于单处理器系统,多个线程分时间片获取CPU或其他系统资源来运行。对于多处理器系统,线程可以分配到多个处理器中,从而真正的并发执行多任务。 7.2填空题 1.________是java程序的并发机制,它能同步共享数据、处理不同的事件。 2.线程是程序中的一个执行流,一个执行流是由CPU运行程序的代码、__________所形 成的,因此,线程被认为是以CPU为主体的行为。 3.线程的终止一般可以通过两种方法实现:自然撤销或者是__________. 4.线程模型在java中是由__________类进行定义和描述的。 5.线程的创建有两种方法:实现_________接口和继承Thread类。 6.多线程程序设计的含义是可以将程序任务分成几个________的子任务。 7.按照线程的模型,一个具体的线程也是由虚拟的CPU、代码与数据组成,其中代码与数 据构成了___________,线程的行为由它决定。 8.ava中,新建的线程调用start()方法、如(),将使线程的状态从New(新建状态)转换为 _________。 9.多线程是java程序的________机制,它能同步共享数据,处理不同事件。 10.进程是由代码、数据、内核状态和一组寄存器组成,而线程是表示程序运行状态的

哲学家就餐问题报告

操作系统 实验报告 实验名称:哲学家就餐问题 班级:信卓1201班 姓名:钟远维 学号:U201213500 日期:2014年10月30日

一、实验目的 1、熟练使用VC6.0编译环境,调试并正确运行程序。 2、理解哲学家就餐问题中出现的问题,进而掌握死锁的必要条件。 3、理解源程序中产生和防止死锁的算法,及相关窗口操作。 4、熟悉哲学家就餐问题流程并写出其伪代码 二、实验内容 有五个哲学家围坐在一圆桌旁(如图1),桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子。每个哲学家的行为是思考,感到饥饿,然后吃通心粉。为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子。 图1 图2 三、实验要求 1、程序需有防止死锁发生采取的措施; 2、程序要有产生死锁的分配方式;

四、实验算法实现 1、不发生死锁的方式 由源码gChopstickState[iLeftChopstick] = iPhilosopher; gChopstickState[iRightChopstick] = iPhilosopher; 知基本思路是要么一下子占用两支筷子要么不占用,先确定两只筷子均没被占用才获取筷子,这样就打破了死锁的必要条件。 伪代码如下; var mutexleftchopstick,mutexrightchopstick; beging: resting; waiting; p(mutexleftchopstick); //先改变左手筷子信号量 p(mutexrightchopstick); //马上改变右手筷子信号量 GetResource(leftchopstick,rightchopstick); //同时占用左右手筷子 eating; v(mutexleftchopstick); //释放资源 v(mutexrightchopstick); end 2、发生死锁的方式 基本思路是有筷子即占用,看似效率很高,但因为资源有限,且不可抢占,很容易发生死锁。 源码理解: gDinerState[iPhilosopher] = WAITING; //wants chopsticks result = WaitForSingleObject(gchopStick[iLeftChopstick], INFINITE); gChopstickState[iLeftChopstick] = iPhilosopher; //得到左手筷子 Sleep(P_DELAY/4); //休眠状态 gDinerState[iPhilosopher] = WAITING; //继续等待另一只手筷子 result = WaitForSingleObject(gchopStick[iRightChopstick], INFINITE); gChopstickState[iRightChopstick] = iPhilosopher; //直到等到右手筷子 伪码书写: var mutexleftchopstick,mutexrightchopstick; beging:

操作系统哲学家进餐问题

操作系统实习 报告 一、设计目的: 死锁是进程并发执行过程中可能出现的现象,所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局。哲学家就餐问题是描述死锁的经典例子。为了防止死锁,可以采用资源预分配法或者资源按序分配法。资源预分配法是指进程在运行前一次性地向系统申请它所需要的全部资源,如果系统当前不能够满足进程的全部资源请求,则不分配资源, 此进程暂不投入运行,如果系统当前能够满足进程的全部资源请求, 则一次性地将所申请的资源全部分配给申请进程。 二、设计内容 哲学家进餐问题的模拟。 三、开发环境 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(),即说明哲学家不能同时处于思考和吃饭的状态中。 public synchronized void thinking() { if(state) /* 如果在思考,说明这个哲学家两边的筷子没用 */ { chopstickArray.getnum(num).setAvailable(true); chopstickArray.getLast(num).setAvailable(true); /*这时哲学家两边的筷子只为可用*/

java多线程实现调度

重庆交通大学综合性设计性实验报告 实验项目名称:进程调度(先来先服务) 实验项目性质: JAVA多线程 实验所属课程: JAVA程序设计 实验室(中心):语音大楼 8 楼 801 班级:软件专业 2012级2班 姓名:尚亚* 学号: 631206050216 指导教师:杨 实验完成时间: 2014 年 11 月 25 日

一、实验目的 1、理解程序、线程和进程的概念; 2、理解多线程的概念; 3、掌握线程的各种状态; 4、熟练使用Thread类创建线程; 5、熟练使用线程各种方法; 6、掌握线程的调度及线程同步的实现原理。 二、实验内容及要求 进程调度是处理机管理的核心内容。本实验要求采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法编写和调试一个简单的进程调度程序。通过本实验可以加深理解有关进程控制块、进程队列的概念。并体会了优先数和先来先服务调度算法的具体实施办法。 用JA V A语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解。做一个能够直观体现多个进程时,CPU 是怎样调度就绪队列中的进程(按照先来先服务的原则)。

三、实验设备 PC机,windows7,eclipse。 四、设计方案 ㈠设计主要思想 (1)要模拟进程的调度算法,必须先体现处进程及系统资源。 (2)要体现先来先服务的算法,就必须表现出当有一个进程进入CPU时其他进程不能进入,并在就绪队列中排队。本实验建立了四个圆移动的线程表示作业调度,用圆在表示就绪队列的方框中停留表示进程在就绪队列中排队。 (3)当有一个圆移动到表示CPU的范围内时,让其它线程在就绪队列中排队,当CPU内无进程时,先来的圆先移动,以表示CPU 对进程的调度。 ㈡设计的主要步骤 (1)建立四个不同颜色的圆移动的线程,表示对四个进程的调度。 (2)当有一个表示进程的圆到达表示CPU范围内时,通过让其它几个圆停留在表示就绪队列的方框范围内,表示进程在就绪队列中排成队列。 (3)当第一个先到达的进程释放CPU,在排成队列的几个圆中选择先到达的圆,使其移动表示对先来的进程进行调度,直到所有的圆移动完毕。 五、主要代码 import java.awt.Font; import java.awt.event.*;

哲学家进餐问题代码

哲学家进餐问题代码(JAVA) (2010-10-12 15:24:12) 转载 标签: 分类:Java it 问题描述: 一个哲学家围坐在一张圆桌周围,每个哲学家面前都有一碟通心面。由于面条很滑,所以 要两把叉子才能夹住。相邻两个碟子之间有一把叉子。 哲学家的生活包括两种活动:即吃饭和思考。当一个哲学家觉得饿时,他就试图分两次去 取他左边和右边的叉子,每次拿一把,但不分次序。如果成功地获得了两把叉子,他就开 始吃饭,吃完以后放下叉子继续思考。 问题是: 为每一个哲学家写一段程序描述其行为。要求不能死锁。 class kuai{ String name; boolean Enable = true; public kuai(String name) { https://www.doczj.com/doc/1b17042922.html, = name; } public synchronized void pickup() { this.Enable =false;

} public synchronized void putdown() { this.Enable =true; this.notifyAll(); } } class Philosopher extends Thread { String name; kuai left; kuai right; public Philosopher(String name, kuai l, kuai r) { https://www.doczj.com/doc/1b17042922.html, = name; left = l; right = r; } public void run() { if(left.Enable) { left.pickup(); } else { while(!left.Enable) {

操作系统课程设计-哲学家进餐问题

潍坊学院计算机工程学院 课程设计说明书 课程名称:____操作系统课程设计_________________设计项目:____哲学家就餐问题____________________学生姓名:_____XXXXXX _________________________学号:____ ___________________专业:______计算机科学与技术________________班级:______一班___________________________指导教师:_______ ___________________________

_2016年__3___月 一、任务与具体要求 哲学家有N个,规定全体到齐后开始讨论,在讨论的间隙哲学家进餐,每人进餐时都需使用刀、叉合一把,所有哲学家刀和叉都拿到后才能进餐。哲学家的人数、餐桌上的布置自行设定,实现刀和叉的互斥使用算法的程序实现。 二、设计说明书包括的内容 1.需求分析 2.系统概要设计 3.系统详细设计 4.系统的主要源代码 5.系统测试及调试 6.总结 7.主要参考文献 三、应完成的图纸 四、评语及成绩 指导教师(签字)_____________

________年____月____日目录 一、需求分析 __________________________________________________________ 1 二、系统概要设计 ______________________________________________________ 2 三、系统详细设计 ______________________________________________________ 3 四、系统的主要源代码 __________________________________________________ 4 五、系统测试及调试 ____________________________________________________ 9 六、总结 _____________________________________________________________ 13 七、主要参考文献 _____________________________________________________ 13

哲学家就餐问题实验报告

南昌大学实验报告 学生姓名:倪焕学号:8000114018 专业班级:软件工程141班 实验类型:■验证□综合□设计□创新实验日期:2016.5.24 实验成绩: 一、实验项目名称 哲学家就餐问题 二、实验目的 利用PV操作解决哲学家就餐问题 三、软硬件环境 软件:Visual Studio2010 硬件:PC机一台 四、实验内容结果 //哲学家就餐问题的解法 #include #include #include #include #include using namespace std; //命名空间std内定义的所有标识符都有效 const unsigned int PHILOSOPHER_NUM=5; //哲学家数目 const char THINKING=1; /*标记当前哲学家的状态,1表示等待,2表示得到饥饿,3表示正在吃饭*/ const char HUNGRY=2; const char DINING=3; HANDLE hPhilosopher[5]; //定义数组存放哲学家 /*HANDLE(句柄)是windows操作系统中的一个概念。指的是一个核心对象在某一个进程中的唯一索引*/ HANDLE semaphore[PHILOSOPHER_NUM]; // semaphore 用来表示筷子是否可用 HANDLE mutex; // Mutex用来控制安全输出 DWORD WINAPI philosopherProc( LPVOID lpParameter) //返回DWORD(32位数据)的API 函数philosopherProc { int myid; //哲学家id char idStr[128];

Java第七单元练习题Java多线程机制

J a v a第七单元练习题 J a v a多线程机制 The latest revision on November 22, 2020

7Java多线程机制 7.1单项选择题 1. 线程调用了sleep()方法后,该线程将进入()状态。 A. 可运行状态 B. 运行状态 C. 阻塞状态 D. 终止状态 2. 关于java线程,下面说法错误的是() A. 线程是以CPU为主体的行为 B. java利用线程使整个系统成为异步 C. 创建线程的方法有两种:实现Runnable接口和继承Thread类 D. 新线程一旦被创建,它将自动开始运行 3. 在java中的线程模型包含() A. 一个虚拟处理器 B. CPU执行的代码 C. 代码操作的数据 D. 以上都是 4.在java语言中,临界区可以是一个语句块,或者是一个方法,并用()关键字标识。 A. synchronized B. include C. import D. Thread 5. 线程控制方法中,yield()的作用是() A. 返回当前线程的引用 B. 使比其低的优先级线程执行 C. 强行终止线程 D. 只让给同优先级线程运行 6. 线程同步中,对象的锁在()情况下持有线程返回 A. 当synchronized()语句块执行完后 B. 当在synchronized()语句块执行中出现例外(exception)时 C. 当持有锁的线程调用该对象的wait()方法时 D. 以上都是 7. 在以下()情况下,线程就进入可运行状态 A. 线程调用了sleep()方法时 B. 线程调用了join()方法时 C. 线程调用了yield()方法时 D. 以上都是 8. java用()机制实现了进程之间的异步执行

编程实现哲学家就餐问题(java)

编程实现哲学家就餐问题。 import java.util.Random; public class Philosoper extends Thread { private String name; private ChopStick leftCS; private ChopStick rightCS; public Philosoper(String name, ChopStick leftCS, ChopStick rightCS) { https://www.doczj.com/doc/1b17042922.html, = name; this.leftCS = leftCS; this.rightCS = rightCS; } public void run() { try { sleep(Random.class.newInstance().nextInt(100)); } catch (Exception e) { e.printStackTrace(); } synchronized (leftCS) { System.out.println(https://www.doczj.com/doc/1b17042922.html, + "has the left chopstick " + leftCS.getName() + "and wait right one" + rightCS.getName() + "..."); synchronized (rightCS) { System.out.println(https://www.doczj.com/doc/1b17042922.html, + "get right chopstick " + rightCS.getName() + " begin to eat!"); } } } class ChopStick { private String name; public ChopStick(String name) { https://www.doczj.com/doc/1b17042922.html, = name; } public String getName() { return name; } }

实验一 哲学家就餐问题

实验一哲学家就餐问题

一、实验目的 1.熟练使用VC++6.0编译环境,调试并正确运行程序。 2.熟悉哲学家就餐问题流程。 3.理解哲学家就餐问题中出现的问题,进而掌握死锁的必要条件。 4.熟悉源程序中产生和防止死锁的算法,及其相关窗口操作。 二、实验原理 1.问题描述: 有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每 两人之间放一只筷子,每个哲学家的行为时思考,饥饿,然后吃通心粉,每个哲学 家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边取筷子。 2.防止死锁发生的分配方式: 仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子。这样要么一次占有两 只筷子(所有线程需要的资源)进行下一步吃通心粉,然后释放所有的资源;要么 不占用资源,这样就不可能产生死锁了。 3.产生死锁的分配方式: 当筷子(资源)可用时,先分配左边的筷子,等待一会后再分配右边的筷子,由于 这个过程中,左边的筷子一直没有释放,就可能产生死锁了。 4.程序运行说明: 程序运行过程中会弹出一个MessageBox提示操作者操作: 1)第一个对话框用于选择运行模式 a.选择yes表示采用的是运行的防止死锁的方式,这样的话整个程序可以一直运行下去,不会产生死锁。 b.选择no表示运行产生死锁的方式会弹出第二个对话框。 2)第二个对话框用于选择运行时,线程运行的时间 a.选择yes线程时间比较短,很快就可以死锁。 b.选择no线程时间跟选择yes时的时间差不多,产生死锁的时间稍微长一点。 三、实验过程及分析 1.PhilosopherThread(LPVOID pVoid)函数伪代码 1)不死锁方式 Var mutexleftchopstick,mutexrightchopstick; Beging: Resting; Waiting; P{mutexleftchopstick}; P{mutexrightchopstick}; GetResource{leftchopstick,rightchopstick}; Eating; V{mutexleftchopstick};

哲学家就餐问题

计算机操作系统哲学家进餐问题的研究 姓名:陆文静 学号: 1310750012 指导老师:杨婷婷 专业班级:软件工程1301班完成时间: 2015年5月4日

哲学家进餐问题研究 摘要: 一、问题的描述 哲学家就餐问题是一种典型的同步问题,它是由Dijkstra提出并解决的。该问题描述如下:有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替的进行思考和进餐。设五个哲学家分别编号为A,B,C,D,E,桌子上放着五只筷子,筷子分别编号为0,1,2,3,4,桌子中央有一盘饭菜,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐毕,放下筷子继续思考。 二、解决问题的方案 1、算法描述 semaphore chopstick[5]={1,1,1,1,1}; do{ wait(room); wait(chopstick[i]); wait(chopstick[(i+1)%5]); eat(); signal(chopstick[i]); signal(chopstick[(i+1)%5]); signal(room); Think; } while[ture]; 以上描述中,可保证不会有两个相邻的哲学家同时进餐,但却有可能引起死锁。假如五位哲学家同时饥饿而各自拿起左边的筷子时,就会使五个信号量chopstick均为0;当他们试图拿右边的筷子时,豆浆因无筷子可拿而无限期地等待,进入死锁状态。 2、改进算法描述 描述一种没有人饿死算法,考虑了四种实现的方式(A、B、C、D) A.原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐, 最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。以下将room 作为信号量,只允许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会出现饿死和死锁的现象。 伪码:semaphore chopstick[5]={1,1,1,1,1}; semaphore room=4; void philosopher(int i) { while(true)

哲学家就餐问题教学内容

哲学家就餐问题

实验一 一、实验名称:哲学家就餐问题的实现 二、实验学时:2 三、实验内容和目的: 实验目的:实现哲学家就餐问题,要求不能出现死锁。通过本实验熟悉Linux 系统的基本环境,了解Linux下进程和线程的实现。 实验内容:在Unix系统下实现教材2.4.2节中所描述的哲学家就餐问题。要求显示出每个哲学家的工作状态,如吃饭,思考。连续运行30次以上都未出现死锁现象。 四、实验原理: 由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。该问题是描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐完毕,放下筷子继续思考。五、实验器材(设备、元器件) (1)学生每人一台PC,安装WindowsXP/2000操作系统。

(2) 局域网络环境。 (3) 个人PC 安装VMware 虚拟机和Ubuntu 系统。 六、实验内容: (一) 熟悉Ubuntu 系统下的多线程编程。 (二)实现哲学家就餐问题 1. 算法思想 规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子,而偶数 号哲学家则相反。按此规定,将是1、2号哲学家竞争1号筷子;3、4号哲学家竞争3号筷子。即五位哲学家都生竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一位哲学家能获得两只筷子而进餐。 2. 流程图 是 否

是 3. 程序代码(重要代码请注释) #include #include #include #include #include #define NOC 5 //number of chopstic #define NOP 5//number of philosopher sem_t chopstic[NOC]; //semaphore int flag[5]; //philosopher's status void *eat(int i){ int position; int temp = 0; int j = (i+1)%NOC; position = i%2; while(1){ if(position == 0){ //odd take left first sem_wait(&chopstic[i]);

java多线程 练习

1.如果线程死亡,它便不能运行。(T) 2.在Java中,高优先级的可运行线程会抢占低优先级线程。(T ) 3.线程可以用yield方法使低优先级的线程运行。(F) 4...程序开发者必须创建一个线程去管理内存的分配。(F) 5.一个线程在调用它的start方法,之前,该线程将一直处于出生期。(T) 6.当调用一个正在进行线程的stop( )方法时,该线程便会进入休眠状态。(F) 7.一个线程可以调用yield方法使其他线程有机会运行。(T) 二、选择题 1.Java语言中提供了一个▁D▁线程,自动回收动态分配的内存。 A.异步 B.消费者 C.守护 D.垃圾收集 2.Java语言避免了大多数的▁C▁错误。 A.数组下标越界 B.算术溢出 C.内存泄露 D.非法的方法参数 3.有三种原因可以导致线程不能运行,它们是▁ACD▁▁。 A.等待 B.阻塞 C.休眠 D.挂起及由于I/O操作而阻塞 4.当▁A方法终止时,能使线程进入死亡状态。 A.run B.setPrority C.yield D.sleep 5.用▁B▁方法可以改变线程的优先级。 A.run B.setPrority C.yield D.sleep 6.线程通过▁C▁方法可以使具有相同优先级线程获得处理器。 A.run B.setPrority C.yield D.sleep 7.线程通过▁D▁方法可以休眠一段时间,然后恢复运行。 A.run B.setPrority C.yield

8.方法resume( )负责重新开始▁D▁线程的执行。 A.被stop( )方法停止 B.被sleep( )方法停止 C.被wait( )方法停止 D.被suspend( )方法停止 9.▁BCD▁方法可以用来暂时停止当前线程的运行。 A.stop( ) B.sleep( ) C.wait( ) D.suspend( ) 三、简述题 1.简述程序、进程和线程之间的关系?什么是多线程程序? 答:程序是一段静态的代码,它是应用软件执行的蓝本。进程是程序的一次动态执行过程,它对应了从代码加载、执行到执行完毕的一个完整过程。这个过程也是进程本身从产生、发展、到消亡的过程。线程是比进程更小的单位。一个进程在其执行过程中,可以产生多个线程,形成多个执行流。每个执行流即每个线程也有它自身的产生、存在和消亡的过程,也是一个动态的概念。多线程程序是指一个程序中包含多个执行流。 2.线程有哪几个基本状态?它们之间如何转化?简述线程的生命周期。 答:新建状态,可运行状态,运行状态,阻碍状态,终止状态。对线程调用各种控制方法,就使线程从一种状态转换到另一种状态。线程的生命周期从新建开始,在可运行、运行和其他阻碍中循环,在可运行、运行、对象锁阻塞、等待阻塞中循环,最终在运行后run()方法结束后终止。 3.什么是线程调度?Java的线程调度采用什么策略? 答:在单个CPU上以某种顺序运行多个线程,称为线程的调度。Java的线程调度策略是一种优先级的抢先式调度。Java基于线程的优先级选择高优先级的线程进行运行。该线程将持续运行,直到它终止运行,或其他高优先级线程称为可运行的。 4.如何在Java程序中实现多线程? 答:1:通过Thread类的构造方法 2:通过实现Runnable接口创建线程、 3:通过继承Thread类创建线程 5.试简述Thread类的子类或实现Runnable接口两种方法的异同? 答:采用继承Thread类方法使程序代码简单,并可以在run()方法中直接调用线程的其他方法。而实现Runnable接口更符合面向对象设计的思想,因为从OO设计的角度,thread 类是虚拟CPU的封装,所以Thread的子类应该是关于CPU行为的类。但在继承Thread类之类构造线程的方法中,Thread类的子类大都是与CPU不相关的类。而实现Runnable接口的方法,将不影响Java类的体系,所以更加符合面向对象的设计思想。同时,实现了Runnable 接口的类可以用extends继承其他的类。 四、程序设计题 1.编写一个类,在类中定义: A:一个整型属性

哲学家吃饭问题 实验报告 操作系统

目录 1.设计题目与要求 (2) 设计目的 设计要求 2.总体设计思想与相关知识 (2) 总体设计思想 问题描述 解决方案 3.数据结构、流程图 (2) 数据结构 流程图 4.源代码 (3) 5.运行结果 (6) 6.结果分析 (7) 7.总结及心得体会 (7)

1.设计题目与要求 设计目的 掌握进程同步问题的解决思路及方法,熟练使用Windows操作系统提供的信号量机制解决各种进程同步问题。 设计要求 设有五个哲学家,共用一张放有五把椅子的餐桌,每人坐在一把椅子上,桌子上有五个碗和五只筷子,每人两边各放一只筷子。哲学家们是交替思考和进餐,饥饿时便试图取其左右最靠近他的筷子。条件: (1) 只有拿到两只筷子时,哲学家才能吃饭。 (2) 如果筷子已被别人拿走,则必须等别人吃完之后才能拿到筷子。 (3) 任意一个哲学家在自己未拿到两只筷子吃饭前,不会放下手中拿到的筷子。 2.总体设计思想与相关知识 总体设计思想 哲学家的生活就是思考和吃饭,即思考,饿了就餐,再思考,循环往复。要求是:每一个哲学家只有在拿到位于他左右的筷子后,才能够就餐;哲学家只能先拿左边的筷子,再去拿右边的筷子,而不能同时去抓他两边的筷子,也不能从其他哲学家手中抢夺筷子;哲学家每次就餐后必须放下他手中的两把筷子后恢复思考,不能强抓住餐具不放。 设计一个程序,能够显示当前各哲学家的状态和桌上餐具的使用情况,并能无死锁的推算出下一状态各哲学家的状态和桌上餐具的使用情况。即设计一个能安排哲学家正常生活的程序。 问题描述 可能出现死锁问题,因为当五个哲学家都饥饿时,都拿着一支筷子,这样就可能五个哲学家都用不上餐。 解决方案 最多允许4个哲学家同时坐在桌子周围。 给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则反之。 为了避免死锁,把哲学家分为三种状态,思考,饥饿,进食,仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子,并且一次拿到两只筷子,否则不拿。3.数据结构及流程图

哲学家就餐问题

实验一 一、实验名称:哲学家就餐问题的实现 二、实验学时:2 三、实验内容和目的: 实验目的:实现哲学家就餐问题,要求不能出现死锁。通过本实验熟悉Linux系统的基本环境,了解Linux下进程和线程的实现。 实验内容:在Unix系统下实现教材2.4.2节中所描述的哲学家就餐问题。要求显示出每个哲学家的工作状态,如吃饭,思考。连续运行30次以上都未出现死锁现象。 四、实验原理: 由Dijkstra提出并解决的哲学家进餐问题(The Dinning Philosophers Problem)是典型的同步问题。该问题是描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐完毕,放下筷子继续思考。 五、实验器材(设备、元器件) (1)学生每人一台PC,安装WindowsXP/2000操作系统。 (2)局域网络环境。 (3)个人PC安装VMware虚拟机和Ubuntu系统。 六、实验内容:

(一)熟悉Ubuntu系统下的多线程编程。 (二)实现哲学家就餐问题 1. 算法思想 规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子,而偶数号哲学家则相反。按此规定,将是1、2号哲学家竞争1号筷子;3、4号哲学家竞争3号筷子。即五位哲学家都生竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一位哲学家能获得两只筷子而进餐。 2. 流程图

3. 程序代码(重要代码请注释) #include #include #include #include #include #define NOC 5 //number of chopstic #define NOP 5 //number of philosopher sem_t chopstic[NOC]; //semaphore int flag[5]; //philosopher's status void *eat(int i){ int position; int temp = 0; int j = (i+1)%NOC; position = i%2; while(1){ if(position == 0){ //odd take left first sem_wait(&chopstic[i]); printf("philosopher%d get %d\n", i, i); sem_wait(&chopstic[j]); printf("philosopher%d get %d\n", i, j); flag[i] = 1; //philosopher is eating printf("waitting:"); //print others' status while(temp < 5){ if(!flag[temp]) printf("philosopher%d\t", temp); temp++; } temp = 0; printf("\n"); printf("eating:");// print others' status

相关主题
文本预览
相关文档 最新文档