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

合集下载

操作系统课程设计利用多线程和信号量解决哲学家进餐问题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的Guarded Suspension模式解决哲学家进餐问题

用Java的Guarded Suspension模式解决哲学家进餐问题

2 哲 学 家 进 餐 问题
哲 学家 进餐 问题 是一 个典 型 的 同步 问题 . 这个 问题 由 Djsa 出 : i t提 kr 五个 哲学 家 围坐在一 张 圆桌 周 围 , 们 的生 活方 式是 交替 地进 行思考 和进 餐 . 上有 五支 筷子 ,每两 个哲 学 家 之间 放 一支 . 学 家饥 他 桌 哲
维普资讯
洛 阳师 范 学 院 学 报 2 0 0 6年 第 2期
・ 1・ 9
用 Jv a a的 Gu r e up nin模 式 解 决 ad dS se s o
哲 学 家 进餐 问题
曹建 立 ,周 震
( 阳师范学 院, 洛 河南 洛阳 4 12 ) 7 02
任 务 的机 制 .
地 支 持 多线 程机 制 , 以方便 地生 成多 线程应 用程 序 , 可 而且 运行 环 境也 利 用 多线程 的技术 并 发 提供 多 项服 务 , “ 圾 ” 如 垃 回收 .aa 言 中提供 了 T ra Jv 语 hed类 ,在类 中封 装 了许 多关 于线 程操 作 的方法 ,如线
程的启动、 运行 、 休眠、 挂起、 恢复 、 退出和终止以及对线程优先级的控制. 并提供 了 s cr i d y h n e 关键 n oz
字来 处 理线 程之 间 的共享 互斥 问题 .
1 2 Gu r e up n in模式 . addS ses o
在该模式下 , 当某个线程对临界资源进行访问时 , 首先需要判断临界资源 的警戒条件是否成立 , 如果成立 , 则可以进行访问; 否则 , 该线程就会执行 w i进入临界资源的等待区( as ) a t w ie 被阻塞起来 , tt 直到 其 他 的线程 改变 了 临界资 源 的状态 , 临界 资源 的警 戒 条件成 立后 , 用 nty l将其 唤 醒. 使 才 of l iA

Java线程同步问题--哲学家就餐

Java线程同步问题--哲学家就餐

Java线程同步问题--哲学家就餐⽬录1.场景2.解决⽅案⽅法⼀:限制吃饭的哲学家⼈数⽅法⼆:找到⼀个左撇⼦哲学家1.场景有五位沉默的哲学家围坐在⼀张圆桌旁,他们⼀⽣都在吃东西和思考。

有五只筷⼦供他们使⽤,哲学家需要双⼿拿到⼀双筷⼦之后才能吃饭;吃完后会将筷⼦放下继续思考。

那么现在有⼀个问题,我们需要想出⼀种⽅案,如何保证哲学家们可以交替吃饭和思考,⽽不会被饿死。

上⾯这个问题是由Dijkstra提出的⼀个经典的线程同步问题。

2.解决⽅案我们在开始想如何解决问题之前,可以先将这个场景通过代码还原,在程序中进⾏建模。

每⼀只筷⼦可以看做是⼀个资源数据,都可以被它两边的哲学家尝试去获取,并且同⼀时间只能由其中⼀⼈持有,这可以通过我们JUC包中的信号量Semaphore来表⽰。

然后,每个哲学家可以看做是⼀个线程,每个线程中的run⽅法内容都是先进⾏思考,然后试图获取左右两边的筷⼦吃饭,吃完饭后继续思考。

通过上⾯的分析,我们的代码实现如下:/*** @author ⼩⿊说Java* @ClassName DiningPhilosophers* @Description 哲学家就餐问题* @date 2022/2/6**/@Slf4jpublic class DiningPhilosophers implements Runnable {private final int id;public DiningPhilosophers(int id) {this.id = id;}private static final Random random = new Random(System.currentTimeMillis());private static final Semaphore[] forks = new Semaphore[5];// 初始化信号量,每个信号量为1,代表1只筷⼦static {forks[0] = new Semaphore(1);forks[1] = new Semaphore(1);forks[2] = new Semaphore(1);forks[3] = new Semaphore(1);forks[4] = new Semaphore(1);}@Overridepublic void run() {try {while (true) {think();eat(id);}} catch (InterruptedException e) {log.error("异常中断", e);}}/*** 哲学家思考随机时间*/private void think() throws InterruptedException {LISECONDS.sleep(random.nextInt(100));}private void eat(int id) {// TODO}}接下来,我们思考⼀下,如何实现哲学家吃饭的逻辑。

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

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

操作系统课程设计——哲学家进餐问题1000字哲学家进餐问题是一个经典的多线程同步问题,在操作系统中有着广泛的应用。

因此,在操作系统课程设计中,探究哲学家进餐问题是一件非常有意义的事情。

哲学家进餐问题的场景是:五个哲学家围坐在一张圆桌前,每个哲学家的左右两侧有一只筷子,他们需要利用这两只筷子才能进餐。

每个哲学家有两种状态:思考和进餐。

当一个哲学家处于进餐状态时,他需要同时获取他左右两侧的筷子,进餐结束后,他会释放这两只筷子,进入思考状态。

在这个场景中,如果所有的哲学家都同时想要进餐,那么就可能会出现死锁情况,即所有的哲学家都拿到了左手边的筷子,但都无法拿到右手边的筷子,导致无法进餐。

因此,需要在代码中实现同步互斥机制,避免死锁的发生。

本课程设计中,我使用了Java语言来实现哲学家进餐问题。

在代码实现中,首先定义了哲学家、筷子、餐桌等对象,然后使用线程来模拟哲学家的思考和进餐过程。

为了避免死锁,我使用了Chandy/Misra算法,即每个哲学家先尝试去取左手边的筷子,如果取不到就不再继续等待,而是重新回到思考状态,等待下一个机会。

同时,当一个哲学家取到了左手边的筷子之后,如果发现右手边的筷子已被占用,他就会释放左手边的筷子,重新回到思考状态,等待下一个机会。

在实现过程中,我还使用了信号量机制,保证了线程间的同步互斥。

每个筷子都是一个二元信号量,初始为1,表示可用。

当一个哲学家拿起筷子时,他会将对应的信号量减1,表示不可用。

当哲学家用完筷子之后,会将对应的信号量加1,表示可用。

通过这种方式,实现了对筷子的访问同步。

最后,我对代码进行了测试,模拟了多位哲学家同时进行进餐的过程。

在测试中,我发现哲学家进餐的速度受到筷子的数量和哲学家思考进餐比例的影响。

当筷子数量少于哲学家数量时,容易出现死锁;当哲学家思考和进餐的时间相当时,程序的运行情况比较稳定。

总的来说,本课程设计实现了哲学家进餐问题,通过学习该问题,我更深入地理解了同步互斥机制的重要性,并学会了如何使用信号量来实现同步互斥。

操作系统课程设计利用多线程和信号量解决哲学家进餐问题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())。

利用Java高级别并发对象求解哲学家进餐问题

利用Java高级别并发对象求解哲学家进餐问题
/ / D i n i n g P h i l o s ph o e r s 5 . j a v a i m p o r t j a v a . u t 1 f . c o n c m ' r e n t . 1 o c k s . ;
i m p o r t j a v a . u t i l . c o n c u r r e n t .・:
S e m a p h o r e : c h o p s t i c k [ 0 ] = c h o p s t i c k [ 1 ] =c h o p s t i c k [ 2 ] = c h ps o t i c k
[ 3 ] = c h o p s t i c k [ 4 ] = 1
1 哲 学 家 进 餐 问题 的 一 种解 法
哲学家进餐问题有很多解法 , 其中的一种解法 是 只有 当哲 学 家 可 以 同时 获 得 两 个 筷 子 ( 临 界 资 源) 时, 才允许哲学家拿起筷子进餐 . 这 种 解 法 的 实质是预先分配哲学家需要的全部资源, 从而预防 死锁 的发 生. 算法 描述 如下 :
V ( c h o p s t i c k [ i ] ) ; V( c h o p s t i c k [ ( i +1 ) %5 } ;
唤醒 P h i o a ph o e r( i + 4 ) %5 ;
唤醒 P h i o s ph o e r( i +1 ) %5 ;
c o n d i t i o n [ j ] = l o c k . n e w C o n d i i t o n ( ) ;
第3 1卷 第 6期
2 0 1 3 年 1 1月
佳 木 斯 大 学 学 报 ( 自 然 科 学 版 )

试验1-哲学家就餐问题

试验1-哲学家就餐问题

实验2. 类、对象、继承及多态实验目的:理解Java对象的面向对象的特征以及在编程中的应用。

实验内容:1、验证对象作为参数传递是引用传递,而普通数据类型为值传递。

2、验证构造方法和静态属性与方法专属于类,而其他属性和方法虽然在类中定义,但是为对象而定义。

3、验证子类对象实例化时,通过继承,不仅将public、protected、缺省的属性和方法拷贝到对象当中,也将父类的私有属性拷贝到对象当中。

4、编写程序,体会类在重载情况下的相互调用,体会构造方法重载的调用方式。

5、编程体现this的三种用法,super的两种用法,指出this.属性在什么情况下不可以省略,指出super.成员方法在什么情况下不能省略,指出this指代对象的作用。

6、设计Src和Dis两个类, Src中有一个被封装的属性,类型为int(要求为非负值),每当我们通过特定方法更改Src对象中的这个属性后,Dis对象都能得到通知,并向Src发消息获得此属性值实验要求:1、程序以能证明和说明实验内容当中提出的问题为实现标准。

2、程序应有良好的书写规范,在类名定义、包名定义、变量定义、常量定义上遵从规范,同时程序在书写上应有良好的缩进层次。

3、实验报告中应有实验体会和收获等方面。

准备工具:1、JDK1.3以上版本,设置环境变量,搭建编译和运行环境。

1、搭建环境。

2、选用Application进行验证。

实验3. 多线程综合设计实验目的:理解Java语言中的多线程和异常处理,并将二者结合起来设计一个综合程序,实现特定的应用功能。

实验内容:1、7名哲学家同桌就餐,演示哲学家就餐问题中死锁现象的出现,并说明原因2、给出一种解决方案,保证多线程下不出现死锁,并说明这样实现的理由实验要求:1、必须有多线程和异常的内容,其中多线程需要处理多线程同步,如还有同步通信则更好;异常需要有异常抛出、异常捕获、异常嵌套捕获等内容,如有自定义异常类则更好。

2、程序当中产生异常的点很多,在一个大的应用程序当中(有众多的类),无论哪种异常发生后,如何集中在一处统一给出中文提示。

哲学家就餐的问题--java实现

哲学家就餐的问题--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;}。

哲学家就餐问题代码

哲学家就餐问题代码
if(chairflg[i][0]==0){ /*the chair is empty*/
chairflg[i][0]=1;
chairflg[i][1]=(int)i;/*philosopher(i) toke the chair*/
break;
}
}
dining_num++;
sem_post(&mutex);
rightIndex = (mythreadId + 1) % PHILOSOPHER_NUM;
myState = THINKING;
while(1)
{
switch(myState)
{
case THINKING:
myState = HUNGRY;
strcpy(strState,"HUNGRY");
break;
if( ret )
{
errNum++;
}
for(i=0;i<PHILOSOPHER_NUM;i++)
{
threadId[i] = i;
sem_init(&semph[i],0,1);
ret=pthread_create(&t_phThread[i], NULL, (void *)philosopher, (void*)(&threadId[i]));
#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;

哲学家就餐问题的算法实现

哲学家就餐问题的算法实现

哲学家就餐问题的算法实现哲学家就餐问题(Dining Philosophers problem)是一个经典的并发算法问题,描述了一群哲学家围坐在圆桌旁就餐的情景。

每个哲学家需要交替地进行思考和进餐,但是他们共享一定数量的餐叉(或者筷子),并且每个哲学家必须同时拿到两把餐叉才能进餐。

这个问题的挑战在于如何避免哲学家之间出现死锁(deadlock)的情况。

下面是一个基于解决哲学家就餐问题的经典算法的实现,这个算法称为"资源分级分配"(Resource Hierarchy Solution):```pythonimport threadingclass Philosopher(threading.Thread):def __init__(self, name, left_fork, right_fork):threading.Thread.__init__(self) = nameself.left_fork = left_forkself.right_fork = right_forkdef run(self):while True:self.think()self.eat()def think(self):print(f"{} is thinking.")def eat(self):print(f"{} is hungry and trying to pick up forks.")fork1, fork2 = self.left_fork, self.right_forkwhile True:fork1.acquire()locked = fork2.acquire(False)if locked:breakfork1.release()print(f"{} swaps forks.")fork1, fork2 = fork2, fork1else:returnself.dining()fork2.release()fork1.release()def dining(self):print(f"{} starts eating.")# 模拟进餐# time.sleep(1)print(f"{} finishes eating.")def main():forks = [threading.Lock() for _ in range(5)]philosophers = []names = ["A", "B", "C", "D", "E"]for i in range(5):philosopher = Philosopher(names[i], forks[i], forks[(i + 1) % 5])philosophers.append(philosopher)philosopher.start()for philosopher in philosophers:philosopher.join()if __name__ == "__main__":main()```这个算法通过引入一个资源层级的概念,保证了哲学家不会陷入死锁的状态。

哲学家就餐问题的算法实现

哲学家就餐问题的算法实现

哲学家就餐问题的算法实现哲学家就餐问题是一个经典的并发计算问题,描述了五个哲学家围坐在一张圆桌前,每个人面前有一碟食物,并且每两个哲学家之间共享一只叉子。

每个哲学家可以执行两个操作:思考和就餐。

当一个哲学家就餐时,他需要同时拿起他的左右两只叉子,并且在就餐完毕后放下叉子。

这个问题的难点在于如何解决可能出现的死锁情况,即每个哲学家都拿起了自己左边的叉子,然后都在等待右边的叉子。

为了避免死锁,需要设计一个算法来保证每个哲学家都能够正确地就餐。

以下是一个可能的解决方案,称为"资源分级"算法:1. 为每个哲学家设计一个状态变量,并初始化为"思考"状态。

2. 每个叉子也有一个状态变量,初始状态为"可用"。

3. 当一个哲学家想要就餐时,他必须拿起他的左右两只叉子。

但是如果有一只或两只叉子已经被其他哲学家持有,他必须等待。

4. 当一个哲学家拿起了他的左右两只叉子时,他可以开始就餐,并将状态变量更新为"就餐"状态。

5. 当一个哲学家就餐完毕后,他将叉子放回桌子上,并将状态变量更新为"思考"状态。

6. 如果一个哲学家发现无法同时拿到他的左右两只叉子,他需要先放下已经持有的叉子,并将状态变量更新为"等待"状态。

然后他等待其他哲学家释放叉子的资源,并尝试再次拿起他的左右两只叉子。

以上是一个简单的"资源分级"算法,可以避免死锁的发生。

但是这个算法可能会导致一些哲学家始终处于等待状态,无法实现公平性。

为了解决这个问题,可以使用更复杂的算法,如Chandy/Misra解法或Dijkstra解法,这些算法可以实现更公平的资源分配。

总结起来,哲学家就餐问题是一个经典的并发计算问题,可能会引发死锁情况。

通过设计合理的算法,如"资源分级"算法或更复杂的解法,可以解决这个问题并保证公平性。

java解哲学家就餐问题

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;}原文出处:中软卓越 。

java处理哲学家问题的设计原理

java处理哲学家问题的设计原理

Java处理哲学家问题的设计原理一、概述1.1 问题概述哲学家问题是由荷兰计算机科学家艾克霍夫(Edsger W. Dijkstra)于1965年提出的一个经典并发编程问题。

问题的描述是:五个哲学家围坐在一张圆桌前,每个哲学家身边有一个餐具(叉子),但只有五把叉子供他们使用。

哲学家的生活由交替的思考和进餐组成。

当哲学家思考时,他们不会占用叉子;当他们饿了时,他们会放下思考,试图拿起他们左右两边的叉子,然后开始进餐。

如果叉子被它旁边的哲学家拿走了,那么这个哲学家就要等待,直至叉子被放回。

这个问题的关键在于如何设计算法来保证每个哲学家都能安全地进餐,同时避免死锁(deadlock)和饥饿(starvation)的产生。

1.2 目的和意义哲学家问题是并发编程领域一个具有挑战性的问题,解决这个问题可以帮助我们深入理解并发编程的原理和机制。

在Java中,通过使用多线程来模拟哲学家问题的场景,可以帮助我们学习并发编程的相关知识,并掌握如何设计出安全、高效的并发程序。

二、相关概念2.1 死锁(deadlock)死锁是指多个进程在执行过程中因争夺资源而造成的一种僵局,彼此都在等待对方释放资源,导致它们都无法继续向前执行的情况。

2.2 饥饿(starvation)饥饿是指某个进程长时间得不到所需的资源,无法继续执行的情况。

在哲学家问题中,如果某个哲学家一直无法获得叉子进餐,就会陷入饥饿状态。

三、问题分析3.1 可能的并发问题在哲学家问题中,可能出现的并发问题主要包括死锁和饥饿。

死锁是因为哲学家之间相互等待对方释放叉子而导致的,而饥饿是因为某个哲学家长时间得不到叉子而无法进餐的情况。

解决这些问题的关键在于设计合理的算法,确保每个哲学家都能安全地进餐,并且避免出现上述的并发问题。

3.2 并发编程的挑战在Java中,实现哲学家问题的并发程序涉及到多线程的使用,而多线程的编程是具有一定挑战性的。

需要考虑线程之间的互斥、同步、协作等问题,确保程序能够正确、高效地执行。

Java哲学家进餐问题多线程

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的筷⼦,另⼀个哲学家⼜拿了这个哲学家右边的筷⼦...依此类推,产⽣循环等待链,即产⽣死锁。

哲学家进餐问题

哲学家进餐问题

哲学家进餐问题作者:未知文章来源:互联网点击数:22 更新时间:2008-10-261.哲学家进餐问题:(1) 在什么情况下5 个哲学家全部吃不上饭?考虑两种实现的方式,如下:A.算法描述:void philosopher(int i) /*i:哲学家编号,从0 到4*/{while (TRUE) {think( ); /*哲学家正在思考*/take_fork(i); /*取左侧的筷子*/take_fork((i+1) % N); /*取左侧筷子;%为取模运算*/eat( ); /*吃饭*/put_fork(i); /*把左侧筷子放回桌子*/put_fork((i+1) % N); /*把右侧筷子放回桌子*/}}分析:假如所有的哲学家都同时拿起左侧筷子,看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子,如此这般,永远重复。

对于这种情况,即所有的程序都在无限期地运行,但是都无法取得任何进展,即出现饥饿,所有哲学家都吃不上饭。

B.算法描述:规定在拿到左侧的筷子后,先检查右面的筷子是否可用。

如果不可用,则先放下左侧筷子,等一段时间再重复整个过程。

分析:当出现以下情形,在某一个瞬间,所有的哲学家都同时启动这个算法,拿起左侧的筷子,而看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此这样永远重复下去。

对于这种情况,所有的程序都在运行,但却无法取得进展,即出现饥饿,所有的哲学家都吃不上饭。

(2) 描述一种没有人饿死(永远拿不到筷子)算法。

考虑了四种实现的方式(A、B、C、D):A.原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。

以下将room 作为信号量,只允许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会出现饿死和死锁的现象。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档