操作系统课程设计利用多线程和信号量解决哲学家进餐问题 java实现
操作系统课程设计利用多线程和信号量解决哲学家进餐问题java实现
操作系统课程设计利用多线程和信号量解决哲学家进餐问题j a v a实现IMB standardization office【IMB 5AB- IMBK 08- IMB 2C】操作系统课程设计课程设计报告课题:利用信号量和多线程机制实现“哲学家进餐”问题所在学院:信息工程学院班级:计科1201学号:4姓名:魏祥指导教师:徐向英2015年1月 1日目录一、课程设计目标 (3)二、课题内容 (3)三、设计思路 (3)四、源代码 (5)五、运行与测试 (9)六、心得体会 (10)一、课程设计目标学习多线程编程,使用线程的同步机制实现“哲学家进餐”问题。
具体要求:1.创建POSIX线程,实现多线程的并发执行,验证多线程共享进程资源的特性。
2.使用互斥量和条件变量,或使用信号量实现线程的同步互斥。
3.验证“哲学家进餐”问题中的死锁情况,并加以解决。
二、课题内容哲学家进餐问题由Dijkstra提出,问题描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,他们的生活方式是交替地进行思考和进餐。
平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。
进餐完毕,放下筷子继续思考。
本次课题要求使用多线程和信号量解决哲学家进餐问题。
并演示产生死锁的情况。
三、设计思路经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许以为哲学家使用。
为了实现对筷子的互斥,可以用一个信号量表示一只筷子,由着五个信号量构成信号量数组。
当哲学家饥饿时总是先去拿左筷子,成功后在拿右筷子。
当五位哲学家同时拿起左筷子,这是每位哲学家都没有右筷子可以拿,就会造成死锁。
思路1:利用记录型信号量设置值为4的记录型信号量,至多只允许四位哲学家同时去拿左筷子().acquire()),只有拿到左筷子,才能继续拿右筷子().acquire())。
拿到两双筷子之后便可以用餐,用餐完毕,先放下左筷子().release()),再放下右筷子().release())。
哲学家就餐问题代码
哲学家就餐问题代码哲学家就餐问题是一个经典的并发编程问题,描述了五位哲学家围坐在圆桌旁,每个哲学家面前有一碗米饭和一只筷子。
哲学家的生活由思考和就餐两个活动组成,思考时不需要筷子,但就餐时需要同时拿起自己左右两边的筷子才能进餐。
问题在于如何设计算法,使得每位哲学家都能够顺利地进行思考和就餐,而不会发生死锁。
以下是一个简单的解决方案,使用Java语言实现:java.import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;class Philosopher implements Runnable {。
private int id;private Lock leftChopstick;private Lock rightChopstick;public Philosopher(int id, Lock leftChopstick, Lock rightChopstick) {。
this.id = id;this.leftChopstick = leftChopstick;this.rightChopstick = rightChopstick;}。
private void think() {。
System.out.println("哲学家 " + id + " 正在思考");try {。
Thread.sleep((long) (Math.random() 1000));} catch (InterruptedException e) {。
e.printStackTrace();}。
}。
private void eat() {。
leftChopstick.lock();rightChopstick.lock();System.out.println("哲学家 " + id + " 正在就餐");try {。
操作系统课程设计——哲学家进餐问题
操作系统课程设计——哲学家进餐问题1000字哲学家进餐问题是一个经典的多线程同步问题,在操作系统中有着广泛的应用。
因此,在操作系统课程设计中,探究哲学家进餐问题是一件非常有意义的事情。
哲学家进餐问题的场景是:五个哲学家围坐在一张圆桌前,每个哲学家的左右两侧有一只筷子,他们需要利用这两只筷子才能进餐。
每个哲学家有两种状态:思考和进餐。
当一个哲学家处于进餐状态时,他需要同时获取他左右两侧的筷子,进餐结束后,他会释放这两只筷子,进入思考状态。
在这个场景中,如果所有的哲学家都同时想要进餐,那么就可能会出现死锁情况,即所有的哲学家都拿到了左手边的筷子,但都无法拿到右手边的筷子,导致无法进餐。
因此,需要在代码中实现同步互斥机制,避免死锁的发生。
本课程设计中,我使用了Java语言来实现哲学家进餐问题。
在代码实现中,首先定义了哲学家、筷子、餐桌等对象,然后使用线程来模拟哲学家的思考和进餐过程。
为了避免死锁,我使用了Chandy/Misra算法,即每个哲学家先尝试去取左手边的筷子,如果取不到就不再继续等待,而是重新回到思考状态,等待下一个机会。
同时,当一个哲学家取到了左手边的筷子之后,如果发现右手边的筷子已被占用,他就会释放左手边的筷子,重新回到思考状态,等待下一个机会。
在实现过程中,我还使用了信号量机制,保证了线程间的同步互斥。
每个筷子都是一个二元信号量,初始为1,表示可用。
当一个哲学家拿起筷子时,他会将对应的信号量减1,表示不可用。
当哲学家用完筷子之后,会将对应的信号量加1,表示可用。
通过这种方式,实现了对筷子的访问同步。
最后,我对代码进行了测试,模拟了多位哲学家同时进行进餐的过程。
在测试中,我发现哲学家进餐的速度受到筷子的数量和哲学家思考进餐比例的影响。
当筷子数量少于哲学家数量时,容易出现死锁;当哲学家思考和进餐的时间相当时,程序的运行情况比较稳定。
总的来说,本课程设计实现了哲学家进餐问题,通过学习该问题,我更深入地理解了同步互斥机制的重要性,并学会了如何使用信号量来实现同步互斥。
基于Java多线程机制解决哲学家进餐问题的深入探究
基于Java多线程机制解决哲学家进餐问题的深入探究
李金忠;孙永萍;夏洁武
【期刊名称】《井冈山大学学报(自然科学版)》
【年(卷),期】2007(028)006
【摘要】简要阐述了操作系统中哲学家进餐这个经典同步问题,探讨了该问题的多种解决策略,并通过Java语言的多线程编程技术,给出了实现此问题相应解决策略的代码,有效地避免了饥饿和死锁现象的产生.
【总页数】4页(P49-52)
【作者】李金忠;孙永萍;夏洁武
【作者单位】井冈山学院信,息科学与传媒学院,江西,吉安,343009;吉安市招标投标中心,江西,吉安,343000;井冈山学院信,息科学与传媒学院,江西,吉安,343009【正文语种】中文
【中图分类】TP314
【相关文献】
1.基于Java多线程机制解决哲学家进餐问题的深入探究 [J], 李金忠;夏洁武;
2.多线程机制解决哲学家进餐问题的解决策略 [J], 李金忠
3.解决哲学家进餐问题陷入死锁状态的系统改造方案分析 [J], 孙时光;张晋
4.通过回退机制解决哲学家进餐问题 [J], 白戈力;付学良
5.基于Java多线程机制解决哲学家进餐问题的深入探究 [J], 李金忠;夏洁武
因版权原因,仅展示原文概要,查看原文内容请购买。
操作系统课程设计利用多线程和信号量解决哲学家进餐问题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())。
操作系统课程设计——哲学家进餐问题
操作系统课程设计课程设计题目:哲学家进餐问题姓名:专业:班级:学号:指导教师:2014年6月10日目录1.设计题目与要求 (2)1.1实验目的 (2)1.2初始条件..............................................................................................错误!未定义书签。
2 总体设计思想及相关知识 (3)2.1总体设计思想 (3)2.2 临界区互斥编程原理 (4)2.3开发环境与工具 (3)3模块说明 (3)3.1 状态改变模块 (4)4. 部分源程序代码及测试结果 (6)5. 课设总结 (9)参考文献 (9)1.设计题目与要求1.1实验目的通过实现哲学家进餐问题的同步,深入了解和掌握进程同步和互斥的原理。
用C++进行线程的创建与撤销代码相对来说比较简单,因为封装比较多,我们能做的就是创建与调用。
当然,代码中也有一些复杂的地方,不是对线程的操作,而是关于界面的显示与操作,单个线程容易创建与撤销,但难的是合理的“监控”与组织多个线程并及时进行状态的显示。
虽然用程序语言实现了进程创建(当然,这是在并不会理论的情况下),但还是没弄清理论的实质。
可能理论更抽象些吧。
在平常的编程中,虽然经常遇到过要使用多线程的问题,但没有去试过从操作系统的角度去考虑线程的运行,在以后的学习中,我想还是会深入了解与学习这方面的东西的。
1.2设计要求哲学家有N个,也定全体到达后开始讨论:在讨论的间隙哲学家进餐,每人进餐时都需使用刀、叉各一把,所有哲学家刀和叉都拿到后才能进餐。
哲学家的人数、餐桌上的布置自行设定,实现刀和叉的互斥使用算法的程序实现。
(1)操作系统:windows(2)程序设计语言:C++(3)设定圆桌上有六个哲学家,三对刀叉,如下图摆放:图1-1 哲学家进餐问题设定图2 总体设计思想及相关知识2.1总体设计思想哲学家的生活就是思考和吃饭,即思考,就餐,再思考,往复循环。
操作系统课程设计——哲学家进餐问题
操作系统课程设计——哲学家进餐问题操作系统课程设计课程设计题目:哲学家进餐问题姓名:专业:班级:学号:指导教师:2014年6月10日目录1.设计题目与要求 (2)1.1实验目的 (2)1.2初始条件 ....... 错误!未定义书签。
2 总体设计思想及相关知识错误!未定义书签。
2.1总体设计思想 ... 错误!未定义书签。
2.2 临界区互斥编程原理 02.3开发环境与工具 (3)3模块说明 (3)3.1 状态改变模块 (4)4. 部分源程序代码及测试结果 (6)5. 课设总结 (5)参考文献 (6)1.设计题目与要求1.1实验目的通过实现哲学家进餐问题的同步,深入了解和掌握进程同步和互斥的原理。
用C++进行线程的创建与撤销代码相对来说比较简单,因为封装比较多,我们能做的就是创建与调用。
当然,代码中也有一些复杂的地方,不是对线程的操作,而是关于界面的显示与操作,单个线程容易创建与撤销,但难的是合理的“监控”与组织多个线程并及时进行状态的显示。
虽然用程序语言实现了进程创建(当然,这是在并不会理论的情况下),但还是没弄清理论的实质。
可能理论更抽象些吧。
在平常的编程中,虽然经常遇到过要使用多线程的问题,但没有去试过从操作系统的角度去考虑线程的运行,在以后的学习中,我想还是会深入了解与学习这方面的东西的。
1.2设计要求哲学家有N个,也定全体到达后开始讨论:在讨论的间隙哲学家进餐,每人进餐时都需使用刀、叉各一把,所有哲学家刀和叉都拿到后才能进餐。
哲学家的人数、餐桌上的布置自行设定,实现刀和叉的互斥使用算法的程序实现。
(1)操作系统:windows(2)程序设计语言:C++(3)设定圆桌上有六个哲学家,三对刀叉,如下图摆放:“等待”->“进餐”:只有一个哲学家处于等待进餐状态,且左右手两边的餐具都处于“空闲”状态时,可以发生这种状态改变。
此状态改变发生后,哲学家拿起左右手两边的餐具。
“进餐”->“思考”:此状态改变发生后,哲学家放下左右手上的餐具。
哲学家就餐的问题--java实现
哲学家就餐的问题--java实现先来看看运⾏结果吧:代码分为4个⽂件:Chopstick.javapackage Philosopher;/*** 表⽰筷⼦的类* */public class Chopstick{public Chopstick(){}public Chopstick(int id){this.id = id;}public boolean isAvailable(){return available;}public void setAvailable(boolean available){this.available = available;}public int getId(){return id;}public void setId(int id){this.id = id;}@Overridepublic String toString(){return "筷⼦" + id;}/*** 表⽰筷⼦是否可⽤* */private volatile boolean available = true;private int id;} ChopstickArray.javapackage Philosopher;public class ChopstickArray{public ChopstickArray(){}public ChopstickArray(int size){chopsticks = new Chopstick[size];for(int i = 0; i < chopsticks.length; ++i){chopsticks[i] = new Chopstick(i);}}public Chopstick getId(int id){return chopsticks[id];}public Chopstick getLast(int id){if(id == 0){return chopsticks[chopsticks.length - 1];}else{return chopsticks[id - 1];}}private Chopstick[] chopsticks;}DiningPhilosophersFrame.javapackage Philosopher;import java.awt.FlowLayout;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;public class DiningPhilosophersFrame extends JFrame{public DiningPhilosophersFrame(){panel2.setLayout(new GridLayout(2, 2, 3, 3));panel2.add(label2);panel2.add(label3);panel2.add(label4);JScrollPane js1 = new JScrollPane(thinkingTextArea,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);JScrollPane js2 = new JScrollPane(eatingTextArea,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);JScrollPane js3 = new JScrollPane(waitingTextArea,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);panel2.add(js1);panel2.add(js2);panel2.add(js3);panel1.setLayout(new FlowLayout());panel1.add(label1);panel1.add(panel2);panel1.add(button);setContentPane(panel1);button.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e){ChopstickArray chopstickArray = new ChopstickArray(5); for(int i = 0; i < 5; i++){new Thread(new Philosopher(i, chopstickArray,thinkingTextArea, eatingTextArea, waitingTextArea)) .start();}}});setSize(300, 400);setVisible(true);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); }public static void main(String[] args){new DiningPhilosophersFrame();}private final JPanel panel1 = new JPanel();private final JPanel panel2 = new JPanel();private final JTextArea thinkingTextArea = new JTextArea(5, 10);private final JTextArea eatingTextArea = new JTextArea(5, 10);private final JTextArea waitingTextArea = new JTextArea(5, 10);JLabel label1 = new JLabel("哲学家问题");JLabel label2 = new JLabel("思考");JLabel label3 = new JLabel("吃饭");JLabel label4 = new JLabel("等待");JButton button = new JButton("开始运⾏");} Philosopher.javapackage Philosopher;import java.util.Random;import javax.swing.JTextArea;public class Philosopher implements Runnable{public Philosopher(){}public Philosopher(int id, ChopstickArray chopstickArray,JTextArea thinkingTextArea, JTextArea eatingtextArea,JTextArea waitingTextArea){this.id = id;this.chopstickArray = chopstickArray;this.thinkingTextArea = thinkingTextArea;this.eatingTextArea = eatingtextArea;this.waitingTextArea = waitingTextArea;}public synchronized void thinking(){if(state){ // 如果在思考,说明这个哲学家两⾯的筷⼦没⽤chopstickArray.getId(id).setAvailable(true);chopstickArray.getLast(id).setAvailable(true);String text = thinkingTextArea.getText();thinkingTextArea.setText(text + this + "在思考\n");try{Thread.sleep(1000);}catch(Exception e){e.printStackTrace();}}state = false;}public synchronized void eating(){if(!state){ // 在思考if(chopstickArray.getId(id).isAvailable()){ // 如果哲学家右⼿边的筷⼦可⽤ if(chopstickArray.getLast(id).isAvailable()){ // 如果左⼿边的筷⼦也可⽤ // 然后将这个能吃饭的哲学家两侧的筷⼦都设置为不可⽤chopstickArray.getId(id).setAvailable(false);chopstickArray.getLast(id).setAvailable(false);String text = eatingTextArea.getText();eatingTextArea.setText(text + this + "在吃饭\n");try{Thread.sleep(1000);}catch(Exception e){e.printStackTrace();}}else{// 右⼿边的筷⼦可⽤,但是左⼿边的不可⽤String str = waitingTextArea.getText();waitingTextArea.setText(str + this + "在等待"+ chopstickArray.getLast(id) + "\n");try{wait(new Random().nextInt(100));}catch(Exception e){e.printStackTrace();}}}else{// 如果哲学家右⼿边的筷⼦不可⽤则等待String str = waitingTextArea.getText();waitingTextArea.setText(str + this + "在等待"+ chopstickArray.getId(id) + "\n");try{wait(new Random().nextInt(100)); }catch(Exception e){e.printStackTrace();}}}state = true;}@Overridepublic void run(){for(int i = 0; i < 10; ++i){thinking();eating();}}@Overridepublic String toString(){return " 哲学家 " + id;}private int id;private boolean state;ChopstickArray chopstickArray;JTextArea thinkingTextArea;JTextArea eatingTextArea;JTextArea waitingTextArea;}。
利用AND信号量机制解决哲学家进餐问题
利⽤AND信号量机制解决哲学家进餐问题哲学家就餐问题是1965年由Dijkstra提出的⼀种线程同步的问题。
问题描述:⼀圆桌前坐着5位哲学家,两个⼈中间有⼀只筷⼦,桌⼦中央有⾯条。
哲学家思考问题,当饿了的时候拿起左右两只筷⼦吃饭,必须拿到两只筷⼦才能吃饭。
上述问题会产⽣死锁的情况,当5个哲学家都拿起⾃⼰右⼿边的筷⼦,准备拿左⼿边的筷⼦时产⽣死锁现象。
解决办法: 1、添加⼀个服务⽣,只有当经过服务⽣同意之后才能拿筷⼦,服务⽣负责避免死锁发⽣。
2、每个哲学家必须确定⾃⼰左右⼿的筷⼦都可⽤的时候,才能同时拿起两只筷⼦进餐,吃完之后同时放下两只筷⼦。
3、规定每个哲学家拿筷⼦时必须拿序号⼩的那只,这样最后⼀位未拿到筷⼦的哲学家只剩下序号⼤的那只筷⼦,不能拿起,剩下的这只筷⼦就可以被其他哲学家使⽤,避免了死锁。
这种情况不能很好的利⽤资源。
package操作系统;class Philosopher extends Thread {private String name;private Fork fork;public Philosopher(String name, Fork fork) {super(); = name;this.fork = fork;}@Overridepublic void run() {thinking();fork.takeFork();eating();fork.putFork();}void eating() {System.out.println("I'm eating " + name);try {sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}void thinking() {System.out.println("I'm thinking" + name);try {sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class Fork {boolean[] used = { false, false, false, false, false };synchronized void takeFork() {String threadName = Thread.currentThread().getName();String name = threadName.substring(threadName.length()-1, threadName.length());int i = Integer.parseInt(name);while (used[i] || used[(i + 1) % 5]) {try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}used[i] = true;used[(i + 1) % 5] = true;}synchronized void putFork() {String threadName = Thread.currentThread().getName();String name = threadName.substring(threadName.length()-1, threadName.length());int i = Integer.parseInt(name);used[i] = false;used[(i + 1) % 5] = false;notifyAll();}}public class哲学家就餐问题 {public static void main(String[] args) {Fork fork = new Fork();new Philosopher("1", fork).start();new Philosopher("2", fork).start();;new Philosopher("3", fork).start();;new Philosopher("4", fork).start();;new Philosopher("5", fork).start();;}}执⾏结果I'm thinking1I'm thinking3I'm thinking2I'm thinking4I'm thinking5I'm eating 1I'm eating 3I'm eating 5I'm eating 2I'm eating 4。
C++操作系统哲学家就餐问题课程设计报告
操作系统课程设计报告133301班20133481 杜闻播20133489 刘景凯20133494 裴硕2015年12月18日目录第一章引言 (1)第二章设计背景 (2)1.1 死锁 (2)1.2死锁产生的条件 (2)1.3 防止死锁 (2)1.3.1资源按序分配法 (3)1.3.2资源预分配法 (3)1.3 哲学家就餐问题 (3)第三章需求分析 (4)1.1 功能需求 (4)1.2 功能模块图 (4)第四章程序设计 (5)4.1 程序流程图 (5)4.2 模块设计 (5)4.3 模块实现 (6)4.3.1 死锁 (6)4.3.2 资源预分配 (7)4.3.3 资源按序分配 (7)第五章程序编码 (7)5.1 程序设计语言 (8)5.2 编程环境 (8)5.3 程序总体设计 (8)5.3.1 包结构设计 (8)5.3.2 总体设计思想 (8)第六章程序调试 (10)6.1 资源按序分配 (10)6.2 资源预分配 (11)6.3 死锁 (11)参考文献 (12)附录1 部分系统界面 (13)附录2 部分源程序 (14)第一章引言操作系统(Operating System,简称OS),是电子计算机系统中负责支撑应用程序运行环境以及用户操作环境的系统软件,同时也是计算机系统的核心与基石。
它的职责常包括对硬件的直接监管、对各种计算资源(如内存、处理器时间等)的管理、以及提供诸如作业管理之类的面向应用程序的服务等等。
死锁是进程并发执行过程中可能出现的现象,哲学家就餐问题是描述死锁的经典例子。
假设有几位哲学家围坐在一张餐桌旁,桌上有吃不尽的食品,每两位哲学家之间摆放着一根筷子,筷子的个数与哲学家的数量相等,每一位哲学家要么思考,要么等待,要么拿起左右两根筷子进餐。
本实验假设有五个哲学家和五根筷子,它们的编号都是从0到4。
如果每位哲学家都拿起左边的筷子,就会发生死锁。
为了防止死锁,可以采用资源预分配法或者资源按序分配法。
java解哲学家就餐问题
java解哲学家就餐问题哲学家进餐问题是一个多线程运用的经典例子,涉及到线程同步/互斥,临界区访问问题以及一个避免死锁的解决方法。
有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之哲学家进餐问题是一个多线程运用的经典例子,涉及到线程同步/互斥,临界区访问问题以及一个避免死锁的解决方法。
有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之间有一支筷子,这样每个哲学家左右各有一支筷子。
哲学家有2个状态,思考或者拿起筷子吃饭。
如果哲学家拿到一只筷子,不能吃饭,直到拿到2只才能吃饭,并且一次只能拿起身边的一支筷子。
一旦拿起便不会放下筷子直到把饭吃完,此时才把这双筷子放回原处。
如果,很不幸地,每个哲学家拿起他或她左边的筷子,那么就没有人可以吃到饭了。
这就会造成死锁了。
这是需要坚决杜绝的,正如操作系统的死锁问题。
代码如下:import java.util.Random;public class DiningPhils{public static void main(String[] args){int n = 10;if( n < 1){System.err.println( "DiningPils <# of philosophers>" );System.exit(-1);}DiningPhils self = new DiningPhils();self.init(n);}public int getCount(){return n;}public void setChopstick( int i, boolean v){chops[ i ] = v;}public boolean getChopstick( int i ){return chops[i];}private void init( final int N){r = new Random();n = ( N < 0 || N > maxPhils ) ? maxPhils : N;chops = new boolean[n];phils = new Philosopher[n];initPhils();dumpStatus();}private void initPhils(){for( int i = 0; i< n; i++ ){phils[i] = new Philosopher( this, i );phils[i].setTimeSlice( generateTimeSlice());phils[i].setPriority( Thread.NORM_PRIORITY - 1);/**哲学家进程降低一级,使所有哲学家进程*全部初始化完毕前不会有哲学家进程抢占主线程*/}while( moreToStart() ){int i = Math.abs( r.nextInt()) % n;if( !phils[i].isAlive()){System.out.println( " ### Philosopher " +String.valueOf( i ) + " started.");phils[i].start();}}System.out.println( "\nPhilosophers Chopsticks" + "\n(1 = eating, 0 = thinking) (1 = taken, 0 = free)"); }public int generateTimeSlice(){int ts = Math.abs(r.nextInt()) % (maxEat + 1);if( ts == 0 )ts = minEat;return ts;}public void dumpStatus(){for( int i = 0; i < n; i++)System.out.print(phils[i].getEat() ? 1 : 0);for( int i = n; i < maxPhils + 4; i++ )System.out.print(" ");for( int i = 0; i < n; i++)System.out.print(chops[i]? 1:0);System.out.println();}private boolean moreToStart(){for( int i = 0; i < phils.length; i++ ){if( !phils[i].isAlive())return true;}return false;}private int n;private Philosopher[] phils;private boolean[] chops;private Random r;private static final int maxPhils = 24; //最多哲学家数 private static final int maxEat = 4; //最多进餐时间 private static final int minEat = 1; //最少进餐时间}class Philosopher extends Thread{public Philosopher( DiningPhils HOST , int i ){host = HOST;index = i;}public void setTimeSlice( int TS ){ts = TS;}public void setLeftChopstick( boolean flag ){host.setChopstick(index, flag);}public void setRightChopstick( boolean flag ){host.setChopstick((index + 1)% host.getCount() , flag);}private void releaseChopsticks(){setLeftChopstick(false);setRightChopstick(false);}public boolean chopsticksFree(){return !host.getChopstick(index) &&!host.getChopstick((index+1)%host.getCount());}public void run(){while(true){grabChopsticks();eat();think();}}private synchronized void grabChopsticks() /**临界区函数,确保哲学家在没有筷子或筷子不够时思考,满足条件后才就餐*/{while( !chopsticksFree()){try{wait();}catch( InterruptedException e){}}takeChopsticks();notifyAll();}private void takeChopsticks(){setLeftChopstick( true );setRightChopstick( true );setEat(true);host.dumpStatus();}private void eat(){pause();setEat( false );releaseChopsticks();}private void think(){pause();}private void pause(){setTimeSlice( host.generateTimeSlice());try{sleep(ts*1000);}catch( InterruptedException e){}}private void setEat(boolean v){isEating = v;}public boolean getEat(){return isEating;}private DiningPhils host;private boolean isEating;private int index;private int ts;}原文出处:中软卓越 。
利用多线程实现哲学家就餐
操作系统课程设计报告题目:利用多线程机制实现“哲学家就餐”所在学院:信息工程学院班级:计科1102学号:**********名:***指导教师:***日期: 2014 年 1 月 7日1.设计目的1.理解“哲学家就餐”模型,掌握基本的同步、互斥算法。
2.理解操作系统中进程和线程的异同,理解并发过程中的死锁现象。
3.掌握Linux多线程创建及并发机制、线程同步机制。
4.掌握和使用Linux POSIX线程接口实现无死锁的哲学家就餐问题。
2.需求分析2.1问题描述有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子,即共5只筷子。
每个哲学家的行为是思考和进餐。
为了进餐,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子。
思考时则同时将两支筷子放回原处(此图中以叉子代表筷子)规则:①只有拿到两只筷子时,哲学家才能吃饭;②如果筷子已经在他人手上,则该哲学家必须等到他人吃完之后才能拿到筷子;③任何一个哲学家在自己没有拿到两只筷子吃饭之前,决不放下自己手中的筷子。
由此出现的问题:可能出现死锁问题,因为当五个哲学家都饥饿时,都拿着一支筷子,这样就可能五个哲学家都用不上餐2.2问题分析该问题可用记录型信号量或者是AND型信号量解决。
记录型信号量解决:经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许一位哲学家使用,为了实现对筷子的互斥使用,可以用一个信号量表示一只筷子,由这五个信号量组成信号量数组。
当哲学家饥饿时总是先拿其左边的筷子,成功后,再去拿右边的筷子,又成功后方可就餐。
进餐完,又先放下他左边的筷子,再放下右边筷子。
这个算法可以保证不会有两个相邻的哲学家同时就餐,但有可能引起死锁。
AND型信号量解决:在哲学家就餐过程中,要求每个哲学家先获得两个临界资源后方能就餐,这在本质上就是AND同步问题,故用AND信号量机制可获得最简洁的解法。
2.3解决方法对于死锁问题可采取这样的几种解决方法:(1)至多只允许四个哲学家同时进餐,以保证至少有一个哲学家可以进餐,最终总会释放出他所用过的两只筷子,从而可使更多的哲学家进餐;(2)仅当左右两只筷子均可用时,才允许哲学家拿起筷子就餐(3)规定奇数号哲学家先拿起右边筷子,然后再去拿左边筷子,而偶数号哲学家则相反。
哲学家吃饭问题(JAVA实现)
import java.util.*; //包含常用的数据类型类
public class Dring name;
public DishWare(String name)
{
=name;
philospher1.start();
philospher2.start();
philospher3.start();
philospher4.start();
}
}
}
catch(InterruptedException e){}
synchronized(Knife)
{ //线程的同步,使用synchronized关键词
System.out.println(this.getNumber()+" has "+Knife.getNumber()+" and wait for "+Fork.getNumber());
private String name;
private static Random random=new Random();
public Philospher(String name,DishWare Knife,DishWare Fork) //构造函数,变量初始化
{
=name;
Philospher philospher3=new Philospher("philospher3",knife2,fork2);
Philospher philospher4=new Philospher("philospher4",fork2,knife1);
哲学家就餐课程设计java
哲学家就餐课程设计java一、教学目标本课程的学习目标包括以下三个方面:1.知识目标:学生能够理解并掌握Java编程语言的基本语法和概念,包括变量、数据类型、运算符、控制结构、数组、字符串等。
2.技能目标:学生能够运用Java编程语言解决实际问题,例如编写简单的程序进行数据计算和输出。
3.情感态度价值观目标:学生能够培养对编程的兴趣和热情,提高自主学习和解决问题的能力。
二、教学内容本课程的教学内容主要包括以下几个部分:1.Java编程语言的基本语法和概念,包括变量、数据类型、运算符、控制结构、数组、字符串等。
2.简单的编程练习和实例,以帮助学生理解和运用所学的知识。
3.针对实际问题的编程解决方法,培养学生的实际编程能力和解决问题的能力。
三、教学方法本课程的教学方法包括以下几种:1.讲授法:教师通过讲解和演示,向学生传授Java编程语言的基本语法和概念。
2.讨论法:学生之间进行讨论和交流,共同解决问题和理解编程的概念。
3.案例分析法:通过分析具体的编程案例,让学生理解编程的实际应用和解决问题的方法。
4.实验法:学生进行编程实验,亲自动手编写代码,培养实际编程能力。
四、教学资源本课程的教学资源包括以下几种:1.教材:Java编程语言的教材,用于学生自学和教师讲解。
2.参考书:提供额外的学习资料和编程实例,帮助学生深入理解和掌握Java编程语言。
3.多媒体资料:包括教学视频、演示文稿等,用于辅助教学和提供visual d。
4.实验设备:计算机和编程环境,用于学生进行编程实验和实际操作。
五、教学评估本课程的评估方式包括以下几个方面:1.平时表现:根据学生在课堂上的参与度、提问和回答问题的表现进行评估。
2.作业:根据学生完成的编程练习和作业的质量进行评估,包括代码的正确性、可读性和创新性。
3.考试:包括期中和期末考试,考试内容涵盖本课程所学的知识和技能,采用客观题和主观题相结合的方式进行评估。
评估方式应客观、公正,能够全面反映学生的学习成果。
Java哲学家进餐问题多线程
Java哲学家进餐问题多线程J a v a实验三多线程哲学家进餐问题5个哲学家共⽤⼀张圆桌,分别坐在周围的5张椅⼦上,在圆桌上有5个碗和5只筷⼦(注意是5只筷⼦,不是5双),碗和筷⼦交替排列。
他们的⽣活⽅式是交替地进⾏思考(thinking)和进餐(eating)。
平时,⼀个哲学家进⾏思考,饥饿时便试图取⽤其左右最靠近他的两只筷⼦,规定他必须先取左边的筷⼦,再取右边的筷⼦。
只有在他拿到两只筷⼦时才能进餐。
进餐完毕,放下筷⼦继续进⾏思考。
假如5位哲学家同时饥饿,各⾃拿起左边的筷⼦时,再去拿各⾃右边的筷⼦,因为⽆筷⼦可拿⽽陷⼊⽆期限等待(死锁)。
进餐完毕释放他⽤过的两只筷⼦,从⽽使更多的哲学家能够进餐。
使⽤Java的多线程同步技术,实现上述解决⽅案。
解决⽅法⼀:破坏循环等待条件最多允许4个哲学家同时去拿左边的筷⼦,即死锁四⼤必要条件之⼀——破坏循环等待条件。
synchronized关键字易混淆处:⽤法:synchronized(⼀个对象){同步代码块}这⾥synchronized锁住的不是这"⼀个对象",⽽是⽤这"⼀个对象"来当看门⼈,只允许⼀个线程来进⼊synchronized锁住的同步{代码块},所以这个代码块被称作“同步代码块”,当代码块执⾏完后,会让这“⼀个对象”(看门⼈),吼⼀声让其它线程进来。
原理是:每⼀个java对象都关联了⼀个“ monitor lock”,当⼀个线程获取了 monitor lock 后,其它线程如果运⾏到获取同⼀个 monitor 的时候就会被 block 住。
当这个线程执⾏完同步代码,则会释放 monitor lock。
下⾯代码,经过分析后能满⾜最多允许4个哲学家同时去拿左边的筷⼦的条件:分析如下:1.如果不加num<4,synchronized(left)后,如果另⼀个哲学家进程拿了right的筷⼦,另⼀个哲学家⼜拿了这个哲学家右边的筷⼦...依此类推,产⽣循环等待链,即产⽣死锁。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统课程设计课程设计报告课题:利用信号量和多线程机制实现“哲学家进餐”问题所在学院:信息工程学院班级:计科1201学号:**********名:**指导教师:***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里面丰富的类库也省去了我编写线程类和信号量类的功夫。
虽然说不必考虑这些,但编写代码的时候我还是遇到了一些问题,多线程的执行和信号量的设置让我话费了一些时间。