哲学家进餐问题

/********************
philosophers.cpp
哲学家进餐问题
在多线程中如何避免死锁。

问题描述:有五位哲学家围绕着餐桌坐,每一位哲学家要么思考
要么等待,要么吃饭。为了吃饭,哲学家必须拿起两双筷子(分
别放于左右两端)不幸的是,筷子的数量和哲学家相等,所以每
只筷子必须由两位哲学家共享

  下面是一种有问题的解法,因为在某个时刻,五个哲学家同时拿起五根左手边的筷子,
  则它们会在同一时候对待右手边的筷子,这样会陷入死锁,但是我测试了,这样的几
  率并不高经过几个小时,还没有出现。但是我们可以肯定,理论上是肯定会出现死锁的,
  我们不能老是靠运气办事,怎么解决这个问题呢
  留给下一步的学习吧

 


  要编译此文件请用多线程版的c++库
********************/

#include <windows.h>
#include <iostream>
#include <process.h>
#include <cstdlib>
#include <ctime>

using namespace std;
unsigned int __stdcall philosopher(void *);

void thinking(int);
void eating(int);
void wait_to_eat(int);

void outline(int ,const char *);

//全局变量
CRITICAL_SECTION crout;//这个变量用来保证输出时不会竞争

CRITICAL_SECTION fork[5];//定义五个临界变量,代表五更筷子

int main(int argc,char *argv[])
{
 void * hthread[5];
 int i;
 unsigned int threadid[5];
 int arg[5];
 int count = 5;
 unsigned long retval;

 
 InitializeCriticalSection(&crout);
 //初始化临界变量
 for(i=0;i<5;i++)
 {
  InitializeCriticalSection(fork + i);
 }
 //创建五个哲学家
 for(i = 0; i<5;i++)
 {
  arg[i] = i;
  hthread[i] = (void *)_beginthreadex(NULL,0,philosopher,(void *)(arg + i),0,threadid+i);
  if((int)hthread[i] == -1)//如果线程创建失败返回-1
  {
   cerr << "error while create thread " << i <<endl;
   cerr << "error code : "<< GetLastError() <<endl;
  }
 }
 //等待所有线程结束
 retval = WaitForMultipleObjects(5,hthread,true,INFINITE);//等待多个线程
 if(retval == WAIT_FAILED)
 {
  cerr<< "wait error,error code: "<<GetLastError()<<endl;
 }
 for(i = 0; i<5;i++)
 {
  if(CloseHandle(hthread[i]) == false)//关闭句柄
  {
   cerr << "error while close thread " <<i<<endl;
   cerr << "error code: "<<GetLastError()<<endl;
  }
 }
 return 0;
}

/*******************
哲学家的行为
吃饭,等待,思考
*******************/

unsigned int __stdcall philosopher(void *k)
{
 int n = ((int *)k)[0];
 
 outline(n," is in!");

 srand(time(NULL));
 while(true)
 {
  thinking(n);
  wait_to_eat(n);
  eating(n);
 }

 outline(n," is out!");

 return n;
}
/*************
思考
随机一段时间
*************/
void thinking(int k)
{
 outline(k," is thinking...");

 Sleep((rand()%1000) *5);
}
/*************
吃饭
随机一段时间
*************/
void eating(int k)
{
 outline(k," is eating...");
 Sleep((rand()%1000) *5);
 LeaveCriticalSection(fork + (k+1)%5);//放下右边的筷子
 //outline(k," give left");
 LeaveCriticalSection(fork + k);//放下左边的筷子
 //outline(k," give right");
}
/***************
等待吃饭
需要同时获得他两边的筷子
***************/
void wait_to_eat(int k)
{
 outline(k," is waiting...");
 EnterCriticalSection(fork + k);//获得左边的筷子
 //outline(k," take left");
 EnterCriticalSection(fork + (k + 1)%5);//获得右边的筷子
 //outline(k," take right");
}
/********************
//没有竞争条件的输出函数
********************/
void outline(int who,const char *str)
{
 EnterCriticalSection(&crout);
 cout<<"process "<<who<<str<<endl;
 LeaveCriticalSection(&crout);
}

 

/********************
philosophers.cpp
哲学家进餐问题
在多线程中如何避免死锁。

问题描述:有五位哲学家围绕着餐桌坐,每一位哲学家要么思考
要么等待,要么吃饭。为了吃饭,哲学家必须拿起两双筷子(分
别放于左右两端)不幸的是,筷子的数量和哲学家相等,所以每
只筷子必须由两位哲学家共享

  下面是一种有问题的解法,因为在某个时刻,五个哲学家同时拿起五根左手边的筷子,
  则它们会在同一时候对待右手边的筷子,这样会陷入死锁,但是我测试了,这样的几
  率并不高经过几个小时,还没有出现。但是我们可以肯定,理论上是肯定会出现死锁的,
  我们不能老是靠运气办事,怎么解决这个问题呢
  留给下一步的学习吧
  要编译此文件请用多线程版的c++库

  WWW.54SH.COM
  MADE BY EFISH

  下面经过了一些修改,把哲学家的个数作为一个宏定义,并减少哲学家的个数为2,

    死锁现象马上出现了,真不走运!
********************/

#include <windows.h>
#include <iostream>
#include <process.h>
#include <cstdlib>
#include <ctime>

#define NUM_OF_PH 2 //哲学家的个数

using namespace std;
unsigned int __stdcall philosopher(void *);

void thinking(int);
void eating(int);
void wait_to_eat(int);

void outline(int ,const char *);

//全局变量
CRITICAL_SECTION crout;//这个变量用来保证输出时不会竞争

CRITICAL_SECTION fork[NUM_OF_PH];//定义五个临界变量,代表五更筷子

int main(int argc,char *argv[])
{
 void * hthread[NUM_OF_PH];
 int i;
 unsigned int threadid[NUM_OF_PH];
 int arg[NUM_OF_PH];
 int count = NUM_OF_PH;
 unsigned long retval;

 
 InitializeCriticalSection(&crout);
 //初始化临界变量
 for(i=0;i<NUM_OF_PH;i++)
 {
  InitializeCriticalSection(fork + i);
 }
 //创建五个哲学家
 for(i = 0; i<NUM_OF_PH;i++)
 {
  arg[i] = i;
  hthread[i] = (void *)_beginthreadex(NULL,0,philosopher,(void *)(arg + i),0,threadid+i);
  if((int)hthread[i] == -1)//如果线程创建失败返回-1
  {
   cerr << "error while create thread " << i <<endl;
   cerr << "error code : "<< GetLastError() <<endl;
  }
 }
 //等待所有线程结束
 retval = WaitForMultipleObjects(NUM_OF_PH,hthread,true,INFINITE);//等待多个线程
 if(retval == WAIT_FAILED)
 {
  cerr<< "wait error,error code: "<<GetLastError()<<endl;
 }
 for(i = 0; i<NUM_OF_PH;i++)
 {
  if(CloseHandle(hthread[i]) == false)//关闭句柄
  {
   cerr << "error while close thread " <<i<<endl;
   cerr << "error code: "<<GetLastError()<<endl;
  }
 }
 return 0;
}

/*******************
哲学家的行为
吃饭,等待,思考
*******************/

unsigned int __stdcall philosopher(void *k)
{
 int n = ((int *)k)[0];
 
 outline(n," is in!");

 srand(time(NULL));
 while(true)
 {
  thinking(n);
  wait_to_eat(n);
  eating(n);
 }

 outline(n," is out!");

 return n;
}
/*************
思考
随机一段时间
*************/
void thinking(int k)
{
 outline(k," is thinking...");

 Sleep((rand()%1000) *NUM_OF_PH);
}
/*************
吃饭
随机一段时间
*************/
void eating(int k)
{
 outline(k," is eating...");
 Sleep((rand()%1000) *NUM_OF_PH);
 LeaveCriticalSection(fork + (k+1)%NUM_OF_PH);//放下右边的筷子
 outline(k," give left");
 LeaveCriticalSection(fork + k);//放下左边的筷子
 outline(k," give right");
}
/***************
等待吃饭
需要同时获得他两边的筷子
***************/
void wait_to_eat(int k)
{
 outline(k," is waiting...");
 EnterCriticalSection(fork + k);//获得左边的筷子
 outline(k," take left");
 EnterCriticalSection(fork + (k + 1)%NUM_OF_PH);//获得右边的筷子
 outline(k," take right");
}
/********************
//没有竞争条件的输出函数
********************/
void outline(int who,const char *str)
{
 EnterCriticalSection(&crout);
 cout<<"process "<<who<<str<<endl;
 LeaveCriticalSection(&crout);
}

 

/********************
philosophers.cpp
哲学家进餐问题
在多线程中如何避免死锁。

问题描述:有五位哲学家围绕着餐桌坐,每一位哲学家要么思考
要么等待,要么吃饭。为了吃饭,哲学家必须拿起两双筷子(分
别放于左右两端)不幸的是,筷子的数量和哲学家相等,所以每
只筷子必须由两位哲学家共享

  下面是一种有问题的解法,因为在某个时刻,五个哲学家同时拿起五根左手边的筷子,
  则它们会在同一时候对待右手边的筷子,这样会陷入死锁,但是我测试了,这样的几
  率并不高经过几个小时,还没有出现。但是我们可以肯定,理论上是肯定会出现死锁的,
  我们不能老是靠运气办事,怎么解决这个问题呢
  留给下一步的学习吧
  要编译此文件请用多线程版的c++库

  WWW.54SH.COM
  MADE BY EFISH

  下面经过了一些修改,把哲学家的个数作为一个宏定义,并减少哲学家的个数为2
  死锁现象马上出现了,真不走运!

  进行了一些改变,把临界变量变成了互斥变量,让每一个哲学家同时等待每一个
  两更筷子
********************/

#include <windows.h>
#include <iostream>
#include <process.h>
#include <cstdlib>
#include <ctime>

#define NUM_OF_PH 3 //哲学家的个数

using namespace std;
unsigned int __stdcall philosopher(LPVOID);

void thinking(int);
void eating(int);
void wait_to_eat(int);

inline void outline(int ,const char *);

//全局变量
CRITICAL_SECTION crout;//这个变量用来保证输出时不会竞争

//CRITICAL_SECTION fork[NUM_OF_PH];//定义五个临界变量,代表五更筷子
//修改之后,用了互斥变量两
void *mutex[NUM_OF_PH + 1];

int main(int argc,char *argv[])
{
 void * hthread[NUM_OF_PH];
 int i;
 unsigned int threadid[NUM_OF_PH];
 int arg[NUM_OF_PH];
 int count = NUM_OF_PH;
 unsigned long retval;

 
// InitializeCriticalSection(&crout);
 //初始化临界变量
 for(i=0;i<NUM_OF_PH;i++)
 {
//  InitializeCriticalSection(fork + i);
  mutex[i] = CreateMutex(NULL,false,NULL);
 }
// mutex[NUM_OF_PH] = mutex[NUM_OF_PH -1];
 //创建五个哲学家
 for(i = 0; i<NUM_OF_PH;i++)
 {
  arg[i] = i;
  hthread[i] = (void *)_beginthreadex(NULL,0,philosopher,(LPVOID)(arg + i),0,threadid+i);
  if((int)hthread[i] == -1)//如果线程创建失败返回-1
  {
   cerr << "error while create thread " << i <<endl;
   cerr << "error code : "<< GetLastError() <<endl;
  }
 }
 //等待所有线程结束
 retval = WaitForMultipleObjects(NUM_OF_PH,hthread,true,INFINITE);//等待多个线程
 if(retval == WAIT_FAILED)
 {
  cerr<< "wait error,error code: "<<GetLastError()<<endl;
 }
 for(i = 0; i<NUM_OF_PH;i++)
 {
  if(CloseHandle(hthread[i]) == false)//关闭句柄
  {
   cerr << "error while close thread " <<i<<endl;
   cerr << "error code: "<<GetLastError()<<endl;
  }
 }
 return 0;
}

/*******************
哲学家的行为
吃饭,等待,思考
*******************/

unsigned int __stdcall philosopher(LPVOID k)
{
 int n = *(int *) k;
 outline(n," is in!");

 srand(time(NULL));
 while(true)
 {
  thinking(n);
  wait_to_eat(n);
  eating(n);
 }

 outline(n," is out!");

 return n;
}
/*************
思考
随机一段时间
*************/
void thinking(int k)
{
 outline(k," is thinking...");

 Sleep((rand()%1000) *NUM_OF_PH);
}
/*************
吃饭
随机一段时间
*************/
void eating(int k)
{
 outline(k," is eating...");
 Sleep((rand()%1000) *NUM_OF_PH);
 /*
 LeaveCriticalSection(fork + (k+1)%NUM_OF_PH);//放下右边的筷子
 outline(k," give left");
 LeaveCriticalSection(fork + k);//放下左边的筷子
 outline(k," give right");
 */
 ReleaseMutex(mutex[k]);
 outline(k," give left");
 ReleaseMutex(mutex[k+1]);
 outline(k," give right");
}
/***************
等待吃饭
需要同时获得他两边的筷子
***************/
void wait_to_eat(int k)
{
 outline(k," is waiting...");
 /*
 EnterCriticalSection(fork + k);//获得左边的筷子
 outline(k," take left");
 EnterCriticalSection(fork + (k + 1)%NUM_OF_PH);//获得右边的筷子
 outline(k," take right");
 */
 //同时等待两根筷子
 WaitForMultipleObjects(2,mutex + k,true,INFINITE);
 outline(k," get two");
}
/********************
//没有竞争条件的输出函数
********************/
void outline(int who,const char *str)
{
 EnterCriticalSection(&crout);
 cout<<"process "<<who<<str<<endl;
 LeaveCriticalSection(&crout);
}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值