哲学家就餐问题代码
利用信号量机制解决哲学家进餐的问题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;}```在主函数中,我们首先定义了哲学家和餐叉的线程以及信号量。
哲学家就餐问题代码
哲学家就餐问题代码哲学家就餐问题是一个经典的并发编程问题,描述了五位哲学家围坐在圆桌旁,每个哲学家面前有一碗米饭和一只筷子。
哲学家的生活由思考和就餐两个活动组成,思考时不需要筷子,但就餐时需要同时拿起自己左右两边的筷子才能进餐。
问题在于如何设计算法,使得每位哲学家都能够顺利地进行思考和就餐,而不会发生死锁。
以下是一个简单的解决方案,使用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. 附件本文档不涉及附件。
利用管程解决哲学家进餐问题
利用管程解决哲学家进餐问题用三种不同状态表示哲学家的活动:进餐、饥饿、思考。
(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。
关于哲学家就餐问题的程序代码分析
关于哲学家就餐问题的程序代码分析: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)哲学家进程:用于分配给哲学家筷子(资源)通过开始运行时候的对话框的选择来控制资源的分配方式:两中分配方式见二、三所述。
哲学家就餐问题
哲学家就餐问题运行环境: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操作系统中的一个概念。
哲学家就餐的问题--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;}。
哲学家就餐问题代码
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()```这个算法通过引入一个资源层级的概念,保证了哲学家不会陷入死锁的状态。
哲学家就餐问题--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.}。
多线程经典哲学家就餐问题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];};。
哲学家进餐问题
哲学家进餐问题作者:未知文章来源:互联网点击数: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 的原则,总会进入到餐厅就餐,因此不会出现饿死和死锁的现象。
哲学家就餐问题一
void test(i) { if(state[i]==HUNGRY&& state[LEFT]!=EATING && state[RIGHT]!=EATING) { up(&s[i]); } }
semaphore mutex=1; //临界区的互斥 semaphore s[N]; //每个哲学家一个信号量 void philosopher( int i) /*i:哲学家编号,从 0到N-1*/ { while(TRUE){} //无限循环 }
void take_chopstick(int i) { down(&mutex); //进入临界区 state[i]=HUNGRY; /*记录哲学家i处于饥 饿的状态*/ test(i); //尝试获取2把筷子 up(&mutex); //离开临界区 down(&s[i]); /*如果得不到需要的筷子阻 塞*/ }
Hale Waihona Puke void put_chopstick(int i) { down(&mutex); //进入临界区 state[i]=THINKING; /*记录哲学家i就餐完 毕*/ test(LEFT); /*检查左边的邻居现在可以 吃吗*/ test(RIGHT); /*检查右边的邻居现在可 以吃吗*/ up(&mutex); //离开临界区 }
哲学家就餐问题一解法
#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 //哲学家进餐 typedef int semaphore ; /*信号量是一特殊整 型数据*/ int state[N]; /*数组用来跟踪记录每位哲学家 的状态*/
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <semaphore.h>
#define PHILOSOPHER_NUM 5
#define THINKING 1
#define HUNGRY 2
#define EATING 3
pthread_mutex_t mutex;
sem_t semph[PHILOSOPHER_NUM];
pthread_t t_threadInfo;
srand(getpid());
pthread_mutex_init(&mutex,NULL);
//ret = pthread_create(&t_threadInfo, NULL, (void *) threadInfo, (void *) NULL);
sem_post(&chopsticks[(i+1)%CHOP_NUM]);
sem_wait(&mutex1);
for(i=0;i<CHAIR_NUM;i++){
if(chairflg[i][1]==(int)i){
chairflg[i][0]=0;
break;
}
}
dining_num--;
sem_post(&mutex1);
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;
#define LEFT (i + PHILOSOPHER_NUM -1)%PHILOSOPHER_NUM //i的左领居编号
#define RIGHT (i + 1)%PHILOSOPHER_NUM //i的右领居编号
int state[PHILOSOPHER_NUM];
void think(int i)
pthread_mutex_init(&mutex,NULL);
for(i=0;i<PHILOSOPHER_NUM;i++)
{
threadId[i] = i;
sem_init(&semph[i],0,1);
pthread_mutex_lock(&mutex);
state[i] = THINKING;
test(LEFT);
test(RIGHT);
pthread_mutex_unlock(&mutex);
}
void philosopher(int *index)
{
int mythreadId = (*index);
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));
for(i=0;i<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;
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/types.h>
#include<errno.h>
#include<unistd.h>
#include<signal.h>
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*/
sleepTime = 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];
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());
if(ret)
{
errNum++;
}
usleep(20);
}
if(errNum)
{
printf("thread create err! errnum=%d \n",errNum);
}
sleep(1);
}
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
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++){
}
}
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)
{
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);
case HUNGRY:
strcpy(strState,"HUNGRY");
if(!(sem_wait(&semph[leftIndex])))
{
if(!(sem_wait(&semph[rightIndex])))
{
myState = EATING;
strcpy(strState,"EATING");
rightIndex = (mythreadId + 1) % PHILOSOPHER_NUM;
myState = THINKING;
while(1)
{
switch(myState)
{
case THINKING:
myState = HUNGRY;
strcpy(strState,"HUNGRY");
break;
sem_post(&chair);
printf("philosopher %d leaves\n",(int)i);
return ((void*)0);
}
$$$$$$$$$$$$$$$$$$$$$$$$$
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#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;//设定信号量