哲学家进餐问题哲学家进餐问题
学家就餐问题 C++ P V原语实现
哲学家就餐问题是一种典型的同步问题,它是由Dijkstra 提出并解决的。该问题描述
:有五个哲学家,他们的生活方式是交替的进行思考和进餐。哲学家们共用一张圆桌,
设五个哲学家分别编号为A,B,C,D,E,桌子上放着五把筷子,筷子分别编号为 0,1,
2,3,4,桌子中央有一盘饭菜。五个哲学家都很有礼貌,都要等同时拿到身旁的两只筷子
才进餐,不然就只是等着继续思考,而且吃了一口之后又马上放下拿起的两根筷子,继续思
考。
用P V原语的方式实现
每个哲学家...
哲学家进餐问题
学家就餐问题 C++ P V原语实现
哲学家就餐问题是一种典型的同步问题,它是由Dijkstra 提出并解决的。该问题描述
:有五个哲学家,他们的生活方式是交替的进行思考和进餐。哲学家们共用一张圆桌,
设五个哲学家分别编号为A,B,C,D,E,桌子上放着五把筷子,筷子分别编号为 0,1,
2,3,4,桌子中央有一盘饭菜。五个哲学家都很有礼貌,都要等同时拿到身旁的两只筷子
才进餐,不然就只是等着继续思考,而且吃了一口之后又马上放下拿起的两根筷子,继续思
考。
用P V原语的方式实现
每个哲学家可用一个线程来模拟,信号量及其P、V操作的实现
定义一个semaphore 类 封装 P V原语模拟函数
(不妨设有6个哲学家,6只筷子, 每只筷子各对应一个信号量且每个信号量初始值应为1)
/***********************semaphore.h*****************************
Semaphore类用于模拟信号量
用法如:Semaphore sem(1);
(1)要求初始信号量值非负
(2)信号量P操作: sem.P();
(3)信号量V操作: sem.V();
****************************************************/
#ifndef SEMAPHORE_H
#define SEMAPHORE_H
#include
class Semaphore{
protected:
HANDLE sem;
public:
//Semaphore();
//void SetValve(int SemValue); Semaphore(unsigned int SemValue);
virtual ~Semaphore();
void P();
void V();
};
#endif
/*****************************semaphore.cpp************************************/
#include
#include
#include
#include "semaphore.h"
Semaphore::Semaphore(unsigned int semValue){
if(semValue > LONG_MAX) semValue = LONG_MAX;
sem = CreateSemaphore(NULL,semValue,LONG_MAX,NULL);
}
Semaphore::~Semaphore(){ CloseHandle(sem);
}
void Semaphore::P(){
DWORD dw = WaitForSingleObject(sem, INFINITE);
assert(dw == WAIT_OBJECT_0);
}
void Semaphore::V(){
ReleaseSemaphore(sem,1,NULL);
}
/*****************************thread.h*************************************
通过startThread开启线程
startThread(PTHREAD_START func,void * param); 用法:
//定义一个PTHREAD_START类型的函数func
unsigned int WINAPI func (void * param){
//...
return 0;
}
//启动一个线程使其执行func函数
startThread(func,NULL);
********************************************************************/
#ifndef THREAD_H
#define THREAD_H
#include
#include
/*
from MSDN :
Start address of a routine that begins execution of a new thread.
For _beginthread, the calling convention is either __cdecl or __clrcall;
for _beginthreadex, it is either __stdcall or __clrcall. WINAPI即为__stdcall
*/
typedef unsigned int (WINAPI *PTHREAD_START) (void *);
/*
chBEGINTHREADEX is From
*/
#define chBEGINTHREADEX(psa, cbStackSize, pfnStartAddr, \ pvParam, dwCreateFlags, pdwThreadId) \ ((HANDLE)_beginthreadex( \ (void *) (psa), \ (unsigned) (cbStackSize), \ (PTHREAD_START) (pfnStartAddr), \ (void *) (pvParam), \ (unsigned) (dwCreateFlags), \ (unsigned *) (pdwThreadId)))
// rename chBEGINTHREADEX to startThread for simplicity #define startThread(pfnStartAddr,pvParam)\
chBEGINTHREADEX(NULL, 0, (pfnStartAddr),(pvParam), 0, NULL)
#endif
/*****************************main函数(主函数)************************************/ 假设偶数号哲学家先拿左边的筷子,右边的哲学家先拿起右边的筷子。
#include
#include "semaphore.h"
#include "thread.h"
#include
#include
#define N 6 //哲学家的个数
#define LEFT(i) (i+N-1)%N //左边的筷子
#define RIGHT(i) (i==N-1)?0:(i+N)%N //右边的筷子 编号为N的哲
学家的右边的筷子编号为0
/*******************************初始化信号量**************************************/ Semaphore
ChopStick[N]={Semaphore(1),Semaphore(1),Semaphore(1),Semaphore(1),Sema
phore(1),Semaphore(1)} ;
/*******************************哲学家状态*******************************************/ void Eating(int Ph_Id)
{
printf("Philosopher%d: \tI'm eating......\t",(int)Ph_Id); }
void Sleeping(int Ph_Id) {
printf("Philosopher%d:\tI'm sleeping......\t",(int)Ph_Id);
Sleep(rand()%10000);
}
void Thinking(int Ph_Id) {
printf("Philosopher%d: \tI'm thinking......\t",(int)Ph_Id);
}
/********************************************************************/
void Philosopher(int pid){ while (true)
{
if (pid%2 == 0) //偶数号哲学家
{
Thinking(pid); //等待中
ChopStick[LEFT(pid)].P(); //先拿起左边的筷子,再拿起右边的筷子 ChopStick[RIGHT(pid)].P(); Eating(pid); //获得的两个信号量则eating ChopStick[LEFT(pid)].V(); //先后释放左右信号量
ChopStick[RIGHT(pid)].V(); printf("\n");
}
else if(pid%2==1 ) //奇数号哲学家
{
Thinking(pid);
ChopStick[RIGHT(pid)].P(); //先拿起右边的筷子,再拿起左边的筷子 ChopStick[LEFT(pid)].P(); Eating(pid); //左右都得到筷子后则eating ChopStick[RIGHT(pid)].V(); //先后释放右左信号量
ChopStick[LEFT(pid)].V(); printf("\n");
}
Sleeping(pid); //吃完睡上一会儿
}
}
int main(){
HANDLE hPhilosopher[N]; //为每个哲学家分配一个线程
int count =0 ;
for (int Philosopher_id =0 ;Philosopher_id5)
break;
}
::WaitForMultipleObjects(N,hPhilosopher,TRUE,INFINITE); for (Philosopher_id = 0 ; Philosopher_id
本文档为【哲学家进餐问题】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。