哲学家就餐问题代码
哲学家就餐问题代码
哲学家就餐问题代码哲学家就餐问题是一个经典的并发编程问题,描述了五位哲学家围坐在圆桌旁,每个哲学家面前有一碗米饭和一只筷子。
哲学家的生活由思考和就餐两个活动组成,思考时不需要筷子,但就餐时需要同时拿起自己左右两边的筷子才能进餐。
问题在于如何设计算法,使得每位哲学家都能够顺利地进行思考和就餐,而不会发生死锁。
以下是一个简单的解决方案,使用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 {。
哲学家进餐问题(操作系统)
哲学家进餐问题(操作系统)哲学家进餐问题(操作系统)1. 引言文档概述:在操作系统领域,哲学家进餐问题是一个经典的并发控制问题。
该问题模拟了五位哲学家围坐在一张圆桌旁,每个哲学家面前放置着一碗面和一只叉子。
哲学家在思考和进餐之间切换,但是他们必须分享叉子来进行进餐。
然而,如果每个哲学家都同时拿起右边的叉子,就会出现死锁的情况。
因此,设计一个合理的算法来解决这个问题是非常重要的。
2. 问题描述2.1 哲学家和叉子在该问题中,有五位哲学家分别编号为 P1、P2、P3、P4、P5,以及五只叉子,编号为 F1、F2、F3、F4、F5.每个哲学家在思考时不会使用叉子,而在进餐时需要使用相邻两只叉子。
2.2 运行过程哲学家的运行过程根据以下步骤进行:- 当一个哲学家饿了后,他会尝试获取左边和右边的叉子。
- 如果两只叉子都可用,哲学家就会进餐,并在完成后释放叉子。
- 否则,哲学家需要等待其他哲学家释放叉子。
3. 解决方案为了解决哲学家进餐问题,我们可以采用以下方法之一:3.1 资源分级分配算法该算法将叉子分为左叉子和右叉子,每个哲学家只能同时拿起左叉子和右叉子。
通过约定哲学家只能按照一定顺序拿起叉子,可以避免死锁的发生。
3.2 资源分级分配算法的伪代码:```acquire_forks(left_fork_id, right_fork_id) {if (left_fork_id < right_fork_id) {acquire(left_fork_id);acquire(right_fork_id);} else {acquire(right_fork_id);acquire(left_fork_id);}}release_forks(left_fork_id, right_fork_id) { release(left_fork_id);release(right_fork_id);}philosopher(id) {while (true) {think();acquire_forks(id, (id + 1) % 5);eat();release_forks(id, (id + 1) % 5);}}```4. 附件本文档不涉及附件。
关于哲学家就餐问题的程序代码分析
关于哲学家就餐问题的程序代码分析:A. Dining.c变量说明:HINSTANCE hInst应用实例句柄HWND hWndMain主窗口句柄HBITMAP hbmpOffscreen位图句柄BOOL bWaitMultiple用于选择等待的方式(要么死锁,要么一直循环运行)BOOL bFastFood;用于选择进程等待的时间extern int gDinerState[]用于表示哲学家的状态(外部接口) extern int gChopstickState[]用于表示筷子的状态extern HANDLEgchopStick[PHILOSOPHERS]筷子的数组函数说明:LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)处理消息函数:根据进程调度的消息的不同处理不同的消息包括:关闭窗口,销毁资源,画窗口,和重画窗口等BOOL CreateOffscreen()获得当前窗口的一个位图句柄void RenderOffscreen(HDC hDestDC)通过位图句柄画演示的界面1.先画桌子,再画筷子,再画盘子,2.再画哲学家:哲学家用圆表示,根据哲学家的状态选择画笔(为resting 状态时为绿色圆圈,为等待或者,就餐时为红色圆圈)3.最后画哲学家的手:判断的依据是若筷子的编号和哲学家的编号一致,那么认为这根筷子属于这个哲学家(筷子资源空闲)那么可以画手表示哲学家获得了这个筷子。
(获得资源)BOOLInitApplication(HINSTANCEhInstance)初始化应用窗口BOOLInitInstance(HINSTANCE hInstance, int nCmdShow)初始化主窗口弹出选择对话框进行模式选择,并启动进程int PASCALWinMain(HINSTANCEhInstance, HINSTANCEhPrevInstance,LPSTR lpCmdLine, intnCmdShow)调用前面的函数并对进线程消息进行处理B.Mutex.c变量说明:extern HWND hWndMain在Dining.c中定义是这个文件的外部接口extern BOOL bWaitMultiple在Dining.c中定义是这个文件的外部接口extern BOOL bFastFood在Dining.c中定义是这个文件的外部接口int gDinerState[PHILOSOPHERS] 哲学家状态数组int gChopstickState[PHILOSOPHERS] 筷子状态数组HANDLEgchopStick[PHILOSOPHERS]筷子状态数组函数说明:1. DWORD WINAPI PhilosopherThread(LPVOID pVoid)哲学家进程:用于分配给哲学家筷子(资源)通过开始运行时候的对话框的选择来控制资源的分配方式:两中分配方式见二、三所述。
哲学家就餐的问题--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;}。
哲学家就餐问题--C原代码
哲学家就餐问题--C原代码/*题目:一群哲学家围坐在一个圆桌,手上持有密码m,并从1开始编了号取初值m,哲学家从1开始报数, 报到m的哲学家停止吃饭,退出圆桌,求哲学家退出的顺序。
要求:n和初值m由完家输入.手上的密码随机产生.最后要打印出编号对应的密码,输出哲学家离开的相后顺序分析:可用循环链表实现,链表数据类型为结构体,记录编号和相应密码,另外设标志哲学家报数的变量mouth, 它的值和哲学家嘴上报的数相等,则如果mouth和m相等,该哲学家就应该离开离开前取他的密码交给m,同时将他的编号放另一单链表numbsave保存。
注意编号要从numbsave的最后节点插入。
当循环链表指向自身时停止比较,这个哲学家即是最后离开的一个.依次打印出numbsave中的数即为按编号哲学家离开的先后顺序。
*/#include "stdio.h"#include "conio.h"#include "stdlib.h"struct philosopher /*哲学家就餐结构体*/{ int number; /*编号*/int password;int mouth; /*嘴上报的数*/struct philosopher *next;};struct philosopher *phead,*pend,*pp;struct numbsave /*存放离开顺序*/{ int numsave;struct numbsave *next;};struct numbsave *top=NULL,*numbnew,*numbthis;void main(void){ char *p,d;int b=1,k,n,m,mouthm=1;clrscr(); gotoxy(9,8);printf("please input n m:");scanf("%d%d",&n,&m); /*n为哲学家人数,m为初始密码*/phead=(struct philosopher *)malloc(sizeof(struct philosopher));pend=phead;phead->mouth=1;for(b=1;b<=n-1;b++) /*给哲学家分配随机密码*/{pend->number=b;k=random(20); /*k为0<kwhile(k<=0)k=random(20);pend->password=k;pp=(struct philosopher *)malloc(sizeof(struct philosopher));pend->next=pp; pend=pp;}pend->number=b; /*最后一位哲学家*/k=random(20); while(k<=0) k=random(20); pend->password=k; pend->next=phead; /*形成循环链表*/printf("\n\tphilosopher number correspondence password as followed:\n\t");pp=phead;for(b=1;b<=n;b++){printf("%d:%d\t",pp->number,pp->password);pp=pp->next;}while(pend->next!=pend){if(phead->mouth==m) /*如果嘴上报数和m相等,意味着一个人要走了*/{pp=phead;phead->next->mouth=1; mouthm=1; /*下一位哲学家从一开始报,mm用于将顺序报出数的交给嘴巴*/phead=pend->next=phead->next; /*两个指针一定要相邻*/numbnew=(struct numbsave*)malloc(sizeof(struct numbsave));m=pp->password; /*修改m的值为离开哲学家的password*/numbnew->numsave=pp->number;if(top==NULL) {top=numbnew; top->next=NULL;} /*离开的哲学家的编号存入numbsave 的最后节点*/else { numbthis=top;while(numbthis->next!=NULL) numbthis=numbthis->next;numbthis->next=numbnew; numbnew->next=NULL;}free(pp);}else {pend=pend->next;phead=phead->next; /*让phead指向下一个*/mouthm++;phead->mouth=mouthm; /*嘴巴说我该报mouthm*/}} /*打印离桌顺序*/printf("\n\tphilosopher away from cookdesk in the follow queue:\n\t");while(top!=NULL){ printf("%d ",top->numsave);top=top->next;}printf("%d ",pend->number); /*这个千万别忘了,他是运气的一位*/printf("\n\tpress any key to go back......");while(!kbhit()) ;}。
哲学家就餐问题
P、V原语解决哲学家就餐问题(C++版本)六个哲学家一起就餐,六只筷子。
为防止哲学家饿死的情况,制定如下规则:规则:(1)奇数号的哲学家先拿起右边的筷子再拿起左边的筷子。
(2)偶数号哲学家先拿起左边的筷子,再拿起右边的筷子。
(3)如果哲学家抢到一只筷子,在抢占另一只筷子时失败,则要放弃已经抢占到的资源。
(4)左右两边都抢到筷子的哲学家,吃完放后释放资源。
源代码如下:1.#include <windows.h>2.#include "semaphore.h"3.#include "thread.h"4.#include <iostream>5.#include <stdio.h>6.#define N 6 //哲学家的个数7.//----------参数说明:-----------------8.// id 左边的筷子9.// (id+1)%N 右边的筷子10.//哲学家和筷子都是从0开始编号11.//编号为N的哲学家的右边的筷子编号为012.13.//初始化信号量14.Semaphore ChopStick[N]={1,1,1,1,1,1} ;15.16.void Philosopher(int id)17.{18. while (true)19. {20. if (id%2 == 0) //偶数号哲学家21. {22. ChopStick[id].P(); //拿起左边的筷子23. ChopStick[(id+1)%N].P(); //拿起右边的筷子24. printf("哲学家%d:正在吃饭/n",id); //左右都得到筷子则吃饭25. ChopStick[id].V(); //释放左边信号量26. ChopStick[(id+1)%N].V();//释放右边信号量27. }28. else if(id%2==1 ) //奇数号哲学家29. {30. ChopStick[(id+1)%N].P(); //拿起右边的筷子31. ChopStick[id].P();//拿起左边的筷子32. printf("哲学家%d:正在吃饭/n",id); //左右都得到筷子则吃饭33. ChopStick[(id+1)%N].V(); //先后释放右左信号量34. ChopStick[id].V();35. }36. Sleep(rand()%1000); //吃完睡上一会儿37. }38.}39.40.int main()41.{42.HANDLE hPhilosopher[N]; //为每个哲学家分配一个线程43. for (int id =0 ;id<N;id++) //开启线程44. {45. hPhilosopher[id] = startThread(Philosopher,id);46. }47. ::WaitForMultipleObjects(N,hPhilosopher,TRUE,INFINITE);48. for (int id = 0 ; id<N;id++)49. {50. CloseHandle(hPhilosopher[id]);51. }52. return 0;53.}。
哲学家就餐问题python
哲学家就餐问题python哲学家就餐问题是一个经典的并发问题,主要涉及到五个哲学家坐在圆桌旁,只有五支筷子,他们思考、拿起筷子、放下筷子都需要时间。
如果两个哲学家同时拿起相邻的两只筷子,就会死锁,因为总会有一个哲学家等待另一只筷子。
以下是一个Python实现的例子:python复制代码import threadingimport randomclass DiningPhilosophers:def__init__(self, n):self.forks = [threading.Lock() for _ in range(n)]self.philosophers = [threading.Thread(target=self.think_and_eat, args=(i,)) for i in range(n)]for philosopher in self.philosophers:philosopher.start()def think_and_eat(self, i):while True:self.think(i)self.eat(i)def think(self, i):print(f"Philosopher {i} is thinking")time.sleep(random.random()) # Thinking takes timedef eat(self, i):left = (i - 1) % 5# Left forkright = (i + 1) % 5# Right forkprint(f"Philosopher {i} is eating")with self.forks[left], self.forks[right]: #拿起左右两边的叉子time.sleep(random.random()) # Eating takes timeprint(f"Philosopher {i} is done eating")# 运行5个哲学家dining_philosophers = DiningPhilosophers(5)在这个实现中,我们使用了Python的threading模块来创建和运行线程,并且每个哲学家都有自己的思考和吃饭的线程。
哲学家进餐问题(操作系统)
哲学家进餐问题(操作系统)哲学家进餐问题(操作系统)介绍:哲学家进餐问题是一个经典的并发算法问题,旨在解决多个哲学家在共享资源(餐叉)上发生死锁的可能性。
这个问题可以帮助我们理解操作系统中的并发问题和资源分配策略。
1、问题描述问题中有N个哲学家坐在一个圆桌周围,每个哲学家面前有一盘食物和一支餐叉。
哲学家的生活可以分为思考和进餐两个状态。
当哲学家进餐时,他需要同时拿起他左右两边的餐叉,进食完毕后再放下餐叉进行思考。
2、算法设计为了解决哲学家进餐问题中的死锁问题,可以采用以下算法设计:2.1、餐叉限制为了避免死锁问题,可以引入餐叉限制策略。
每个哲学家一开始只能拿起右手边的餐叉,在用餐完毕后再放下餐叉,然后才能拿起左手边的餐叉。
这样,如果每个哲学家都只拿起右手边的餐叉,不会出现餐叉死锁的情况。
2.2、同时判断两个餐叉是否可用为了避免哲学家同时拿起两个餐叉造成资源竞争问题,可以引入一个全局锁,每次只有一个哲学家可以同时判断两个餐叉是否可用并取走。
3、代码实现以下是解决哲学家进餐问题的伪代码实现:```initialize();while (true) {think(); // 哲学家思考pickup_forks(); // 拿起餐叉eat(); // 哲学家进食putdown_forks(); // 放下餐叉}```4、系统流程图以下是哲学家进餐问题的系统流程图:(此处添加哲学家进餐问题的系统流程图)5、相关附件本文档未附带相关附件,请根据实际需求添加。
6、法律名词及注释本文档没有涉及法律名词及注释。
哲学家进餐问题
哲学家进餐问题作者:未知文章来源:互联网点击数: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 的原则,总会进入到餐厅就餐,因此不会出现饿死和死锁的现象。
【精选资料】哲学家就餐问题代码
【精选资料】哲学家就餐问题代码#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 5int chairflg[CHAIR_NUM][2],dining_num=0;sem_tchair,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<chop_num;i++)< bdsfid="90" p=""></chop_num;i++)<>{sem_init(&chopsticks[i],0,1);}sem_init(&mutex,0,1);sem_init(&mutex1,0,1);sem_init(&print_mutex,0,1);for(i=0;i<4;i++)chairflg[i][0]=0;/*create the threads*/for(i=0;i<num_threads_p;i++)< bdsfid="100" p=""></num_threads_p;i++)<>pthread_create(&threads_p[i],NULL,(void*)philosopher_thre ad,(void*)(i));/*wait the threads to exit*/for(i=0;i<num_threads_p;i++)< bdsfid="104" p=""></num_threads_p;i++)<>pthread_join(threads_p[i],NULL);/*destroy the semaphores*/sem_destroy(&chair);sem_destroy(&chopsticks[CHOP_NUM]);sem_destroy(&mutex);sem_destroy(&mutex1);sem_destroy(&print_mutex);return 0;}void* philosopher_thread(int tid){int i;i=tid;sem_wait(&chair);sem_wait(&mutex);for(i=0;i<chair_num;i++){< bdsfid="121" p=""></chair_num;i++){<>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);sem_wait(&chopsticks[i]);printf("philosopher %d get chopstics %d\n",i,i);sem_wait(&chopsticks[(i+1)%CHOP_NUM]);printf("philosopher %d get chopstics %d\n",tid,(i+1)%CHOP_NUM);sleep(rand()%3);sem_wait(&print_mutex);printf("philosopher %d is dining.when he is dining ,there are %d philosophers at table.\n",(int)i,dining_num);for(i=0;i<chair_num;i++){< bdsfid="138" p=""></chair_num;i++){<>if(chairflg[i][0]==1){printf("poilosopher %d in chair %d. ",chairflg[i][1],i+1);}}printf("\n\n");sem_post(&print_mutex);sleep(rand()%3);sem_post(&chopsticks[i]);sem_post(&chopsticks[(i+1)%CHOP_NUM]);sem_wait(&mutex1);for(i=0;i<chair_num;i++){< bdsfid="150" p=""></chair_num;i++){<>if(chairflg[i][1]==(int)i){chairflg[i][0]=0;break;}}dining_num--;sem_post(&mutex1);sem_post(&chair);printf("philosopher %d leaves\n",(int)i);return ((void*)0);}$$$$$$$$$$$$$$$$$$$$$$$$$#include#include#include#include#include#define PHILOSOPHER_NUM 5#define THINKING 0#define HUNGRY 1#define EATING 2pthread_mutex_t mutex;sem_t semph[PHILOSOPHER_NUM];#define LEFT (i + PHILOSOPHER_NUM -1)%PHILOSOPHER_NUM //i 的左领居编号#define RIGHT (i + 1)%PHILOSOPHER_NUM //i 的右领居编号int state[PHILOSOPHER_NUM];void think(int i){}void eat(int i){}void test(int i){if((state[i] == HUNGRY )&& (state[LEFT] != EATING)&& (state[RIGHT]!= EATING)) {state[i] = EA TING;sem_post(&semph[i]);}}void take_forks(int i){pthread_mutex_lock(&mutex); state[i] = HUNGRY;test(i);pthread_mutex_unlock(&mutex); sem_wait(&semph[i]);}void put_forks(int i){pthread_mutex_lock(&mutex); state[i] = THINKING;test(LEFT);test(RIGHT);pthread_mutex_unlock(&mutex); }void philosopher(int *index) {int mythreadId = (*index);int sleepTime;bzero(state,0);while(1){think(mythreadId);take_forks(mythreadId);eat(mythreadId);put_forks(mythreadId);// sleep a random time : between 1 - 5 ssleepTime = 1 + (int)(5.0*rand()/(RAND_MAX+1.0));usleep(sleepTime*10);}}int main(){int i,ret;int threadId[PHILOSOPHER_NUM];int errNum=0;pthread_t t_phThread[PHILOSOPHER_NUM];pthread_t t_threadInfo;srand(getpid());pthread_mutex_init(&mutex,NULL);//ret = pthread_create(&t_threadInfo, NULL, (void *) threadInfo, (void *) NULL);if( ret ){errNum++;}for(i=0;i<philosopher_num;i++)< bdsfid="244"p=""></philosopher_num;i++)<>{threadId[i] = i;sem_init(&semph[i],0,1);ret=pthread_create(&t_phThread[i], NULL, (void *)philosopher, (void*)(&threadId[i]));if(ret){errNum++;}usleep(20);}if(errNum){printf("thread create err! errnum=%d \n",errNum);}sleep(1);}#include#include#include#include#include#define PHILOSOPHER_NUM 5#define THINKING 1#define HUNGRY 2#define EATING 3pthread_mutex_t mutex;sem_t semph[PHILOSOPHER_NUM];void philosopher(int *index){int mythreadId;char myState,strState[128];int leftIndex;int rightIndex;int sleepTime;mythreadId = (*index);leftIndex = mythreadId + PHILOSOPHER_NUM-1)% PHILOSOPHER_NUM;rightIndex = (mythreadId + 1) % PHILOSOPHER_NUM;myState = THINKING;while(1){switch(myState){case THINKING:myState = HUNGRY;strcpy(strState,"HUNGRY");break;case HUNGRY:strcpy(strState,"HUNGRY");if(!(sem_wait(&semph[leftIndex]))){if(!(sem_wait(&semph[rightIndex]))){myState = EATING;strcpy(strState,"EATING");}else{//不能同时拿起则都不拿起sem_post(&semph[leftIndex]);}}break;case EATING:sem_post(&semph[leftIndex]);sem_post(&semph[rightIndex]);myState=THINKING;strcpy(strState,"THINKING");break;}pthread_mutex_lock(&mutex);printf("pholosopher %d begin %s\n",mythreadId,strState);pthread_mutex_unlock(&mutex);sleepTime = 1+(int)(5.0*rand()/(RAND_MAX+1.0));usleep(sleepTime);}}int main(){int i,ret;int threadId[PHILOSOPHER_NUM];int errNum=0;pthread_t t_phThread[PHILOSOPHER_NUM];//pthread_t t_threadInfo;srand(getpid());pthread_mutex_init(&mutex,NULL);for(i=0;i<philosopher_num;i++)< bdsfid="335" p=""></philosopher_num;i++)<>{threadId[i] = i;sem_init(&semph[i],0,1);ret=pthread_create(&t_phThread[i], NULL, (void *)philosopher, (void*)(&threadId[i]));if(ret){errNum++;}usleep(20);}if(errNum){printf("thread create err! errnum=%d \n",errNum);}sleep(1);}%%%%%%%%%%%%%%%%%%%1.#include2.#include3.#include4.#include5.#include6.#include7.8.#define PEOPLE_NUM 59.#define THINKING 110.#define HUNGRY 211.#define EATING 312.13.sem_t chopsticks[PEOPLE_NUM];14.pthread_mutex_t mutex;15.16.void *philosopher(void *arg){17.int id = (int) arg;18.19.int state = THINKING;20.int right = (id + 1) % PEOPLE_NUM;21.int left = (id + PEOPLE_NUM - 1) % PEOPLE_NUM;22.char ptrState[32];23.24.while(1){25.switch(state){26.case THINKING:27. usleep(300);28. state = HUNGRY;29. strcpy(ptrState,"Thinking before eat");30.break;31.case HUNGRY:32. strcpy(ptrState,"Hungry");33.if(sem_wait(&chopsticks[left]) == 0){//阻塞状态34.if(sem_trywait(&chopsticks[right]) == 0){//非阻塞35. strcpy(ptrState,"I will Eating");36. state = EATING;37. }else{38. state = THINKING;39. strcpy(ptrState,"I have not chopsticks");40. sem_post(&chopsticks[left]);//释放请求的得到的left筷子41. printf("Philosopher right chopsticks is busy,right=%d,th read id is %d\n",right,id);42. }43. }else{44. printf("Philosopher left chopsticks is busy,left=%d,thread id is %d\n",left,id);//这句话由于上面被阻塞永远不会输出45. }46.break;47.case EATING:48. printf("Philosopher fetch left and right chopsticks: (%d,%d), threadid is %d\n",left,right,id);49. sem_post(&chopsticks[left]);50. sem_post(&chopsticks[right]);51. printf("Philosopher release left and right chopsticks: (%d,%d),threadid is %d\n",left,right,id);52. usleep(500);53. state = THINKING;54. strcpy(ptrState,"Thinking after eat");55.break;56. }57. pthread_mutex_lock(&mutex);58. printf("Philosopher is %s, thread id is %d\n",ptrState,id);59. pthread_mutex_unlock(&mutex);60. usleep(1000);61. }62.63. pthread_exit((void*)0);64.}65.66.int main(){67. pthread_t tid[PEOPLE_NUM];68.int i;69. pthread_mutex_init(&mutex,NULL);70.for(i = 0 ; i < PEOPLE_NUM ; i ++){71. sem_init(&chopsticks[i],0,1);72. }73.for(i = 0 ; i < PEOPLE_NUM ; i ++){74. pthread_create(&tid[i],NULL,philosopher,(void*)i);75. }76.for(i = 0 ; i < PEOPLE_NUM ; i ++){77. pthread_join(tid[i],NULL);78. }79.return 0;}#include#include#include#include#include#include#include#include#define N 5 //哲学家的人数#define LEFT (i+N-1)%N //i的左边邻居编号#define RIGHT (i+1)%N //i的右边邻居编号#define THINKING 0 //哲学家在思考#define HUNGRY 1 //哲学家试图拿起叉子#define EATING 2 //哲学家进餐int mutex; //缓冲区信号量(含有1个)) int semphilosopher; //哲学家状态信号量(含有5个)char *state; //哲学家状态int shmid; //共享内存区union semun { //对信号量控制的命令参数int val;struct semid_ds *buf;ushort *array;}arguement;int newshm(){shmid = shmget(IPC_PRIVATE, N, IPC_CREAT|0660);if(shmid < 0){return 0;}return 1;}int doshmat(){state = (char*)shmat(shmid, (void*)0, 0);if(state == (void*)-1){return 0;}return 1;}int newsem(){//每个哲学家的信号量初始化为0arguement.val = 0;semphilosopher = semget(IPC_PRIVATE, N, IPC_CREAT|0660);//创建一个哲学家信号量集合if(semphilosopher == -1) { printf("create semphilosopher error!n"); return0;}for(int i=0; i<="" p="">{if (semctl(semphilosopher,i,SETVAL,arguement) <0)//(semphilosopher,i)表示控制信号量集合中的第i个信号量return 0;}//缓冲区的信号量初始化为1arguement.val = 1;mutex = semget(IPC_PRIVATE,1,IPC_CREAT|0660);if (mutex < 0) return 0;if (semctl(mutex,0,SETVAL,arguement) < 0)return 0;return 1;}void p_operator(int semid, int member)//P操作{struct sembuf sem_op={ member, -1, SEM_UNDO };semop(semid, &sem_op, 1);}void v_operator(int semid, int member)//V操作{struct sembuf sem_op={ member, 1, SEM_UNDO };semop(semid, &sem_op, 1);}void think(int i){state[i] = THINKING;printf("philosopher%d is thinking!n",i);sleep(3);}void eat(int i){printf("philosopher%d is eating!n",i);sleep(3);}void finish(int i){printf("philosopher%d has ended eating!n",i);sleep(2);}void test(int i){if (state[i]==HUNGRY && state[LEFT]!=EATING && state[RIGHT]!=EATING){state[i] = EATING;printf("philosopher%d has took two forks and will start eating!n",i);v_operator(semphilosopher, i);}}void take_forks(int i){p_operator(mutex, 0);state[i] = HUNGRY;test(i);v_operator(mutex, 0);p_operator(semphilosopher, i); }void put_forks(int i){p_operator(mutex, 0);state[i] = THINKING;test(LEFT);test(RIGHT);v_operator(mutex, 0);}void philosopher(int i){think(i);take_forks(i);eat(i);put_forks(i);finish(i);think(i);}main(){int current,pc;if(newshm()==0){printf("newshm error!n"); return 1;}if(doshmat()==0){printf("newshm error!n");return 1;}if(newsem()==0){printf("newsem error!n");return 1;}for(int i=0; i<="" p="">{while((pc=fork())<0);if(pc == 0){current = i;break;}}if(pc > 0){wait(state);shmctl(mutex, IPC_RMID, 0); //删除与第一个参数对应的物理存储空间shmctl(semphilosopher, IPC_RMID, 0);shmdt(state); //切断逻辑地址与内存的联系shmctl(shmid, IPC_RMID, 0);printf("all child process ended!n");}elsephilosopher(current);exit(0);}。
利用信号量机制解决哲学家进餐的问题c语言
利用信号量机制解决哲学家进餐的问题c语言哲学家进餐问题是经典的并发编程问题,主要是模拟多个哲学家同时在桌子上进行吃饭和思考。
由于每个哲学家都需要同时拿起左右两边的餐叉才能进餐,如果不加以控制,容易导致死锁的情况发生。
为了解决这个问题,可以利用信号量机制来确保每个哲学家同时只能拿到一把餐叉,从而避免死锁的发生。
首先,我们需要定义一些全局变量和信号量来表示哲学家和餐叉的状态。
```c#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <semaphore.h>#define N 5 // 哲学家的数量pthread_t philosophers[N]; // 哲学家的线程pthread_mutex_t forks[N]; // 餐叉的互斥锁sem_t room; // 哲学家就餐的信号量void *philosopher(void *arg) {int id = *(int *)arg;int right = id;int left = (id + 1) % N;while (1) {// 思考sleep(rand() % 3 + 1);// 请求餐叉sem_wait(&room);pthread_mutex_lock(&forks[right]);pthread_mutex_lock(&forks[left]);// 进餐sleep(rand() % 3 + 1);printf("Philosopher %d is eating\n", id + 1);// 放下餐叉pthread_mutex_unlock(&forks[left]);pthread_mutex_unlock(&forks[right]);sem_post(&room);}}int main() {int i, id[N];// 初始化互斥锁和信号量sem_init(&room, 0, N - 1); // 初始信号量为N-1,表示有N-1个座位可供就餐for (i = 0; i < N; i++) {pthread_mutex_init(&forks[i], NULL);}// 创建哲学家线程for (i = 0; i < N; i++) {id[i] = i;pthread_create(&philosophers[i], NULL, philosopher, &id[i]); }// 等待哲学家线程结束for (i = 0; i < N; i++) {pthread_join(philosophers[i], NULL);}// 销毁互斥锁和信号量for (i = 0; i < N; i++) {pthread_mutex_destroy(&forks[i]);}sem_destroy(&room);return 0;}```在主函数中,我们首先定义了哲学家和餐叉的线程以及信号量。
利用管程解决哲学家进餐问题
利用管程解决哲学家进餐问题用三种不同状态表示哲学家的活动:进餐、饥饿、思考。
(thinking,hungry,eating)state[5];为第i个(i=0,..,4)哲学家设置一个条件变量self[i],当哲学家饥饿又不能获得筷子时,用self[i].wait来阻塞自己。
condition self[5];管程设置三个函数:pickup取筷子,putdown放筷子,test测试是否具备进餐条件。
?Monitor DP;(thinking, hungry, eating) state[5] ;condition self[5];void Entry pickup(int i) /*第i号哲学家取筷子*/{ state[i] = hungry; test(i);if(state[i]!=eating) self[i].wait;}void Entry putdown(int i) /*第i号哲学家放下筷子*/{ state[i] = thinking;test((i+4)%5); test((i+1)%5);}void test(int i) /*测试第i号哲学家是否具备进餐条件*/{if (state[(i+4) % 5]<>eating) && (state[i]=hungry) && (state[(i+1) % 5]<>eating){ state[i] = eating; self[i].signal; }}{ (for i = 0; i < 5; i++) state[i] = thinking;}cobeginvoid philosopher(int i){while(true){thinking; DP.pickup(i); eating;DP.putdown(i); }}coend。
哲学家就餐问题
哲学家就餐问题运行环境:linux 2.6.38-8 generic代码及说明:/** philosopherEating.cpp** Author: 郭浩东,梁仲海*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>#include <semaphore.h>#include <string.h>//共有5个哲学家#define PEOPLE_NUM 5//思考状态#define THINKING 1//饥饿状态#define HUNGRY 2//吃的状态#define EATING 3//5根筷子sem_t chopsticks[PEOPLE_NUM];//有一把互斥锁pthread_mutex_tmutex;void *philosopher(void *arg){//对于某个哲学家,id号int id = (int) arg;//初始状态设置为THANKINGint state = THINKING;int right = (id + 1) % PEOPLE_NUM;//右边的哲学家idint left = (id + PEOPLE_NUM - 1) % PEOPLE_NUM;//左边的哲学家id charptrState[32];//5个哲学家不断争夺资源while(1){switch(state){case THINKING:usleep(300);//如果是思考状态,则思考300usstate = HUNGRY;//变为饥饿状态strcpy(ptrState,"Thinking before eat");break;case HUNGRY:strcpy(ptrState,"Hungry");if(sem_wait(&chopsticks[left]) == 0){//阻塞状态if(sem_trywait(&chopsticks[right]) == 0){//非阻塞strcpy(ptrState,"I will Eating");state = EATING;}else{state = THINKING;strcpy(ptrState,"I have not chopsticks");sem_post(&chopsticks[left]);//释放请求的得到的left 筷子printf("Philosopher right chopsticks is busy,right=%d,thread id is %d\n",right,id);}}else{printf("Philosopher left chopsticks is busy,left=%d,thread id is %d\n",left,id);//这句话由于上面被阻塞永远不会输出}break;case EATING:printf("Philosopher fetch left and right chopsticks: (%d,%d), threadid is %d\n",left,right,id);sem_post(&chopsticks[left]);//释放左边的筷子sem_post(&chopsticks[right]);//释放右边的筷子printf("Philosopher release left and right chopsticks: (%d,%d), threadid is %d\n",left,right,id);usleep(500);state = THINKING;//吃完后继续转换为思考状态strcpy(ptrState,"Thinking after eat");break;}pthread_mutex_lock(&mutex);printf("Philosopher is %s, thread id is %d\n",ptrState,id);pthread_mutex_unlock(&mutex);usleep(1000);}pthread_exit((void*)0);}int main(){//存储5个哲学家的id号pthread_ttid[PEOPLE_NUM];inti;pthread_mutex_init(&mutex,NULL);//初始化互斥锁for(i = 0 ; i< PEOPLE_NUM ; i ++){sem_init(&chopsticks[i],0,1);//初始化资源型信号量}for(i = 0 ; i< PEOPLE_NUM ; i ++){pthread_create(&tid[i],NULL,philosopher,(void*)i);//创建5个线程代表5个哲学家,开始争夺筷子}for(i = 0 ; i< PEOPLE_NUM ; i ++){pthread_join(tid[i],NULL);//挂起}return 0;}运行结果截图:运行环境:windows10IDE:codeblocks代码及说明://哲学家就餐问题的解法#include <windows.h>#include <process.h>#include <time.h>#include <stdlib.h>#include <stdio.h>#include <iostream>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操作系统中的一个概念。
多线程经典哲学家就餐问题C++113种实现
多线程经典哲学家就餐问题C++113种实现哲学家就餐问题核⼼是 避免死锁1. 同时拿起左右叉⼦class DiningPhilosophers {public:DiningPhilosophers(){}void wantsToEat(int philosopher,function<void()> pickLeftFork,function<void()> pickRightFork,function<void()> eat,function<void()> putLeftFork,function<void()> putRightFork){int r =(philosopher+1)%5;mtx.lock();// 要么左右⼀起拿,要么都不拿lock[philosopher].lock();lock[r].lock();pickLeftFork();pickRightFork();mtx.unlock();eat();putRightFork();putLeftFork();lock[r].unlock();lock[philosopher].unlock();}private:std::mutex lock[5];std::mutex mtx;};2. 改变就餐策略(奇数先拿右,偶数先拿左)class DiningPhilosophers {public:DiningPhilosophers(){}void wantsToEat(int philosopher,function<void()> pickLeftFork, function<void()> pickRightFork, function<void()> eat,function<void()> putLeftFork, function<void()> putRightFork){ int l = philosopher;int r =(philosopher+1)%5;if(philosopher &1){lock[r].lock();lock[l].lock();pickRightFork();pickLeftFork();}else{lock[l].lock();lock[r].lock();pickLeftFork();pickRightFork();}eat();putLeftFork();putRightFork();lock[l].unlock();lock[r].unlock();}private:std::mutex lock[5];};3. 限定就餐⼈数(4个⼈就餐)class Semaphore {public:Semaphore(){}void set_count(int k){count = k;}void signal(){unique_lock<std::mutex>lock(mtx);++count;cv.notify_one();}void wait(){unique_lock<std::mutex>lock(mtx);while(count <=0)cv.wait(lock);--count;}private:int count;std::mutex mtx;std::condition_variable cv;};class DiningPhilosophers {public:DiningPhilosophers(){sem.set_count(4);}void wantsToEat(int philosopher,function<void()> pickLeftFork, function<void()> pickRightFork, function<void()> eat,function<void()> putLeftFork, function<void()> putRightFork){ int l = philosopher;int r =(philosopher+1)%5;sem.wait();lock[l].lock();lock[r].lock();pickLeftFork();pickRightFork();eat();putLeftFork();putRightFork();lock[l].unlock();lock[r].unlock();sem.signal();}private:Semaphore sem;std::mutex lock[5];};。
关于哲学家就餐问题的分析代码.
关于哲学家就餐问题的分析代码.①总体思路: 都去拿左边的筷⼦,并且最后⼀个⼈不能去拿筷⼦(防⽌⼤家都拿了左边的筷⼦,没有右边的筷⼦,导致死锁了),解决死锁问题的办法就是同时只允许四位哲学家同时拿起同⼀边的筷⼦,这样就能保证⼀定会有⼀位哲学家能够拿起两根筷⼦完成进⾷并释放资源,供其他哲学家使⽤,从⽽实现永动,避免了死锁。
举个最简单的栗⼦,假定0~3号哲学家已经拿起了他左边的筷⼦,然后当4号哲学家企图去拿他左边的筷⼦的时候,将该哲学家的线程锁住,使其拿不到其左边的筷⼦,然后其左边的筷⼦就可以被3号哲学家拿到,然后3号哲学家进餐,释放筷⼦,然后更多的哲学家拿到筷⼦并进餐。
如何才能实现当4号哲学家企图拿起其左边的筷⼦的时候将该哲学家的线程阻塞?这个时候就要⽤到该问题的提出者迪杰斯特拉(这货还提出了迪杰斯特拉最短路径算法,著名的银⾏家算法也是他发明的)提出的信号量机制。
因为同时只允许有四位哲学家同时拿起左筷⼦,因此我们可以设置⼀个信号量r,使其初始值为4,然后每当⼀位哲学家企图去拿起他左边的筷⼦的时候,先对信号量做⼀次P操作,从⽽当第五位哲学家企图去拿做筷⼦的时候,对r做⼀次P操作,r = -1,由r < 0得第五位哲学家的线程被阻塞,从⽽不能拿起左筷⼦,因此也就避免了死锁问题。
然后当哲学家放下他左边的筷⼦的时候,就对r做⼀次V操作。
②在主线程和⼦线程中,避免了竞争关系.代码参考如下:/************************************ @file linux_zexuejia.c* @copyright ⽉光下的脚步 Co.,Ltd.ALL Right Reserved* @brief 使⽤信号量和互斥锁完成,哲学家就餐问题。
* @author 王有康* @data 2019、7、31* @version V1.1* @Last Modified 2018/10/25 wangyoukang* @note 当前版本是v1.1版本,以后需要修改,可以在上添加版本和修改⽇期* @note* @warning* @Function List :************************************/#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <time.h>#include <unistd.h>#include <pthread.h>#include <semaphore.h>#define N 5//互斥锁pthread_mutex_t chops[N];//信号量sem_t r;/*********************** @fn philosopher* @biref 每次只有4个⼈能够获得左⼿资源,这样不会死锁* @param philosopher number* @return* @other***********************/void philosopher(void *arg){int i = *(int *)arg;int left = i;int right = (i + 1)%N;while(1){printf("哲学家%d在思考问题\n",i);usleep(1000);printf("哲学家%d饿了\n",i);sem_wait(&r);pthread_mutex_lock(&chops[left]);printf("philosopher %d take left lock\n",i);pthread_mutex_lock(&chops[right]);printf("philosopher %d take right lock\n",i);printf("philosopher %d eat\n",i);usleep(1000);pthread_mutex_unlock(&chops[right]);printf("philosopher %d release right lock\n",i);pthread_mutex_unlock(&chops[left]);printf("philosopher %d realease left lock\n",i);sem_post(&r);}}/*********************** @fn philosopher* @biref 主函数* @param* @return* @other***********************/int main(int argc,char **argv){int i = 0,*ptr;pthread_t tid[N];for(i = 0;i < N;i++){pthread_mutex_init(&chops[i],NULL);}sem_init(&r,0,4);for(i = 0;i < N;i++){//防⽌主线程和对等线程竞争,给线程和主线程分配不同的内存区域。
6个哲学家进餐问题预防死锁
红河学院课程设计报告操作系统课程名称:6个哲学家进餐设计题目:院系:工学院专业:计算机科学与技术班级:11计科班曹永前设计者:学号:201101030466指导教师:韦相2013 年 5 月26 日1. 问题描述:一个房间内有6个哲学家,他们的生活就是思考和进食。
哲学家思考后,过一定的时间就会饥饿,饥饿之后就想吃饭,吃饭后再思考。
房间里有一张圆桌,桌子周围放有五把椅子,分别属于五位哲学家每两位哲学家之间有一把叉子,哲学家进食时必须同时使用左右两把叉子。
2. 问题分析1、写出哲学家进餐的算法描述。
用六只筷子解决需要用两双筷子来进餐的六个哲学家,由于每个哲学家都需要其周围的两只筷子,所以筷子是公用信号量,这久需要设置一个互斥信号量,来使六个哲学家互斥的进餐.具体做法将六个信号量设置为0-5,用pv 源于来控制信号量,并将六个哲学家分别编号为0-5.经过仔细分析我们会发现,有这样一个问题存在,就是当每个哲学家都申请到他周围的一只筷子时,由于他们每人都只有一只筷子无法进餐,没有进餐他们就无法释放他们已经得得到的筷子,这样是进餐出于一种僵局,无法继续下去,这就是死锁问题.2、死锁问题的分析与具体的解决方法。
死锁问题就是当每个哲学家都拿到且只拿到一只筷子,这样每个哲学家都无法进餐,也无法释放所得到的筷子,所以解决死锁我们就要从这入手,就是怎样去预防使所有哲学家不要同时去申请他们同一方向的筷子.根据这解决死锁的方法有以下几种:a.每一次最多只能有五个哲学家申请进餐.这样其中的一个哲学家就能申请到两只筷子,就能够进餐,再将筷子释放给其他哲学家进餐.b.用AND信号量,就是哲学家需同时申请其左右两边的筷子,两边都有资源的时候,才能让这个哲学家得到资源,这样哲学家只要申请到筷子就能进餐, 再将筷子释放给其他哲学家进餐.c.用管程机制来实现。
d.我们前面已经将每个哲学家都分配了一个编号,我们可以编号为奇数的哲学家首先去申请其左边的筷子,再去申请其右手边的筷子;让编号为偶数的哲学家,先去申请其右边的筷子,再去申请其左边的筷子.我们可以看出编号为奇数的哲学家左边,与编号为偶数的哲学家的右边为同一只筷子,当其中一个哲学家拿到此筷子后,他另一边的筷子也是空闲的,这样就能避免死锁.主程序中我使用的是最后一种避免死锁的方法.3、用C程序实现哲学家进餐。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <iostream>
#include <iomanip>
#include <ctime>
#include <cstdlib>
using namespace std;
enum State {THINK,WAIT,EAT,END};//哲学家所处状态
bool p(int &a);
bool v(int &a);
class phi//哲学家
{
public:
phi();
~phi();
void again();//让哲学家回到构造时的状态
int living(int &r,int &l);//哲学家活着在
State getsta();//返回哲学家状态
int getinlet();//得到入口
void print();//输出状态
private:
State sta;//哲学家状态
int inlet;//入口。
哲学家应该在做什么?
};
int main()
{
srand((unsigned)time(NULL));
phi p[5];//5个哲学家
int cho[5]={1,1,1,1,1};//5根筷子
int check1,check2,n=0;char c;
cout<<"输入y看死锁情况!"<<endl;
cin>>c;
while(true)
{
int i;
check1=0;check2=0;//check1检察状态是否全为等待,check2检验是否全部吃完
for(i=0;i<5;i++)
{
if(c=='y')p[i].living(cho[i],cho[(i+4)%5]);
else{
if(i%2==0)p[i].living(cho[i],cho[(i+4)%5]);//偶数号先右后左
else p[i].living(cho[(i+4)%5],cho[i]);//奇数号先左后右
}
}
cout<<setw(8)<<"哲学家:";
for(i=0;i<5;i++)p[i].print();
cout<<endl;
cout<<setw(8)<<"筷子:"<<" ";
for(i=0;i<5;i++)
{
cout<<setw(8)<<cho[i];
if(p[i].getsta()==WAIT)check1++;
if(p[i].getinlet()==10)check2++;//等于12时筷子都交公完了!
}
cout<<endl;
if(check1==5){
cout<<"死锁!!!!"<<endl;
break;
}
if(check2==5){
if(c=='y'){
n++;
cout<<"第"<<n<<"次..."<<endl;
for(i=0;i<5;i++)p[i].again();
}
else{
cout<<"都吃完饭了!!!"<<endl;
break;
}
}
}
return 0;
}
bool p(int &a)
{
if(a==1){
a--;
return true;
}
else return false;//由于同用一根筷子的人数只有两个,全局看,程序不用设等待队列
}
bool v(int &a)
{
a++;
return true;//能交出来,你手上肯定有筷子。
}
phi::phi()
{
sta=THINK;
inlet=0;
}
phi::~phi()
{
}
void phi::again()
{
sta=THINK;
inlet=0;
}
int phi::living(int &r,int &l)
{
if(inlet==0){
int p1=rand()%2;
if(p1==1)inlet++;//肚子饿了,要开吃了!!!!
}
else if(inlet==1){
if(p(r)){//申请筷子
sta=WAIT;
inlet++;//如果分配成功则进入下一阶段,否则等待下次申请
}
}
else if(inlet==2){
if(p(l)){//申请筷子
sta=EAT;
inlet++;//分配成功。
进入下一阶段
}
}
else if(inlet>2&&inlet<7){//相当于吃饭需要吃一段时间
inlet++;
}
else if(inlet==7){
int p2=rand()%2;
if(p2==1)inlet++;//决定哲学家是否还要断续吃
}
else if(inlet==8){
sta=END;//终于吃完了,交出筷子吧
v(l);
inlet++;
}
else if(inlet==9){//加到11就执行
v(r);
inlet++;
}
else ;//??
return 0;
}
State phi::getsta()
{
return sta;
}
int phi::getinlet()
{
return inlet;
}
void phi::print()
{
if(sta==THINK){cout<<setw(8)<<"思考";}
else if(sta==WAIT){cout<<setw(8)<<"等待";}
else if(sta==EAT){cout<<setw(8)<<"用餐";}
else {cout<<setw(8)<<"吃完";}
}。