多线程模拟哲学家就餐问题

本文介绍了哲学家就餐问题,一个经典的多线程同步问题。通过应用CRITICAL_SECTION变量,作者在VC6环境下编写了源码,模拟了哲学家在就餐、思考状态间的切换,以防止死锁的发生。源码经过作者测试,可以在VC6下运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                    多线程模拟哲学家就餐问题
                                         -----Amoon    2005/09/23


1)问题描述

 学操作系统的进程同步都要涉及到三个经典问题:生产者-消费者问题、读者-写者问题和哲学家就餐问题。下面来介绍一下哲学家就餐问题: 哲学家就餐问题中,一组哲学家围坐在一个圆桌旁,每个哲学家的左边都只有一只筷子(当然他的右边也有一只筷子,但是这是他右边哲学家的左边的筷子),他们吃完了就思考,思考了一会就会饿,饿了就想吃,然而,为了吃饭,他们必须获得左边和右边的筷子。当每个哲学家只拿有一只筷子的时候,会坐者等另一只筷子,在每个哲学家都只拿一个筷子的时候,就会发生死锁。

2)关于源码的一点说明:
 
 应用CRITICAL_SECTION 变量解决数据共享问题。

3)vc6下源码如下( 经作者在vc6下测试通过运行 ):

#include <windows.h>
#include <process.h>    /* _beginthread, _endthread */
#include <time.h>
#include <fstream>
#include <string>
#include <iostream>
#include <assert.h>
#include <time.h>

using namespace std;


ofstream out("out.txt");
BOOL b[6];//共享数据,用于表示 5 双筷子的使用情况,FALSE代表被占用
CRITICAL_SECTION cs;

class philosopher
{
private:
 int m_num;    //编号
 int m_index;  //标示装态,0-------waiting   1-----eating    2-----thinking

 BOOL m_lhand; //true -----筷子空闲,false----筷子被占用  
 BOOL  m_rhand;

public:
 philosopher(int num=0) { m_num=num; m_index=2; m_lhand=TRUE; m_rhand = FALSE ;}

 int GetNum() const { return m_num; }

 int GetStatus() const { return m_index ; }

 void ChangeStatus() ;   
};

void philosopher::ChangeStatus()

 EnterCriticalSection (&cs) ;

 if(m_index==1)  //eating----->thinking
 { 
  assert(!b[m_num]);
  b[m_num]=TRUE;

  if( m_num==1)
  {
   assert(!b[5]);
   b[5]= TRUE;
  }
  else
   b[m_num-1]=TRUE;

  m_index=2;   // change to thinking
  srand(time(NULL)*10000);
  Sleep(rand()%10);
 }

 else if( m_index==2)    //thinking
 { 
  m_index=0;   //change to waiting
  
 }
 else if( m_index==0)    // waiting
 { 

  if(m_num==1)
  {
   if(b[1]&&b[5])
   {
    b[1]=FALSE;
    b[5]=FALSE;
    m_index=1;
    srand(time(NULL)*10000);
    Sleep(rand()%10);
   }
  }
  else
  { 
   
   if(b[m_num]&&b[m_num-1])
   {
    b[m_num]= FALSE;
    b[m_num-1]= FALSE;
    m_index=1;
    srand(time(NULL)*10000);
    Sleep(rand()%10);
   }
  }


 }
 LeaveCriticalSection (&cs) ;

}

//ust to out the philosopher info
 
string PrintStatus(philosopher *pPh)
{
 pPh->ChangeStatus();
 int i=pPh->GetStatus();
 string str;
 if(i==0)
  str="Waiting";
 else if(i==1)
  str="eating";
 else str="thinking";
 return str;
}

void ThreadFunc1(PVOID param)

 while(1)
 
 {
  philosopher *pPh;
  pPh=( philosopher *) param;
  pPh->ChangeStatus();


 }
 
}
void ThreadFunc2(PVOID param)

 while(1)
 {
  philosopher *pPh;
  pPh=( philosopher *) param;
  pPh->ChangeStatus();
 }
}
void ThreadFunc3(PVOID param)

 while(1)
 {
  philosopher *pPh;
  pPh=( philosopher *) param;
  pPh->ChangeStatus();
 }
}
void ThreadFunc4(PVOID param)

 while(1)
 {
  philosopher *pPh;
  pPh=( philosopher *) param;
  pPh->ChangeStatus();
 }
}
void ThreadFunc5(PVOID param)

 while(1)
 {
  philosopher *pPh;
  pPh=( philosopher *) param;
  pPh->ChangeStatus();
 }
}


int main()
{
 
 for(int j=1;j<=5;j++) b[j]=TRUE;
  out<<b[1]<<b[2]<<b[3]<<b[4]<<b[5];
 philosopher ph1(1),ph2(2),ph3(3),ph4(4),ph5(5);
 InitializeCriticalSection (&cs) ;

 _beginthread(ThreadFunc1,0,&ph1);
 _beginthread(ThreadFunc2,0,&ph2);
 _beginthread(ThreadFunc3,0,&ph3);
 _beginthread(ThreadFunc4,0,&ph4);
 _beginthread(ThreadFunc5,0,&ph5);
 cout<<"press ctrl+C to exit";
 while(1)
 { 
  out<<endl<<b[1]<<b[2]<<b[3]<<b[4]<<b[5]<<endl;   // use  to test
  out<<"The status at :"<<clock()<<" ms "<<endl;
  out<<"哲学家"<<ph1.GetNum() <<"所处状态:"<<ph1.GetNum()<<"--"<<PrintStatus(&ph1)<<endl;
  out<<"哲学家"<<ph2.GetNum() <<"所处状态:"<<ph2.GetNum()<<"--"<<PrintStatus(&ph2)<<endl;
  out<<"哲学家"<<ph3.GetNum() <<"所处状态:"<<ph3.GetNum()<<"--"<<PrintStatus(&ph3)<<endl;
  out<<"哲学家"<<ph4.GetNum() <<"所处状态:"<<ph4.GetNum()<<"--"<<PrintStatus(&ph4)<<endl;
  out<<"哲学家"<<ph5.GetNum() <<"所处状态:"<<ph5.GetNum()<<"--"<<PrintStatus(&ph5)<<endl;

  Sleep(20);
 }

 DeleteCriticalSection (&cs) ;

 return 0;
}


评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值