睡眠理发师问题

 一 问题描述 
  (经典理发师问题) 
  假设后街有家理发店,店里有一个理发师、一把理发椅和n把等候理发的顾客椅子。 
  (1).如果没有顾客则理发师便在理发椅上看报纸; 
  (2).当有一个顾客到达时,首先查看理发师在干什么,如果在看报纸则告诉理发师理发,然后坐到理发椅上开始理发;如果理发师正在理发,则查看是否有空的椅子可坐,如果有,他就坐下等待,如果没有,则离开; 
  (3).理发师为一位顾客理完发后,查看是否有人等待,如有则唤醒一位为其理发,如没有则在理发椅上看报纸; 
  (4).顾客不分优先级 
  二 问题分析 
  题目中要求描述理发师和顾客的行为,因此需要两类进程Barber ()和Customer()分别描述理发师和顾客的行为。当理发师看报时顾客近来需要唤醒理发师为其理发,当有顾客时理发师为其理发,没有的时候理发师看报,因此理发师和顾客之间是同步的关系,由于每次理发师只能为一个人理发,且可供等侯的椅子有限只有n个,即理发师和椅子是临界资源,所以顾客之间是互斥的关系。故引入3个信号量和一个控制变量:1)控制变量waiting用来记录等候理发的顾客数,初值均为0;2)信号量customers用来记录等候理发的顾客数,并用作阻塞理发师进程,初值为0;3)信号量barbers用来记录正在等候顾客的理发师数,并用作阻塞顾客进程,初值为0;4)信号量mutex用于互斥,初值为1 
  三 问题实现 
  1.PV操作代码如下: 
  int waiting=0 ; //等候理发的顾客数 
  int chairs=n; //为顾客准备的椅子数 
  semaphore customers=0, barbers=0,mutex=1; 
  barber() 
  { 
  while(TRUE); //理完一人,还有顾客吗? 
  P(cutomers); //若无顾客,理发师睡眠 
  P(mutex); //进程互斥 
  waiting := waiting – 1; //等候顾客数少一个 
  V(barbers); //理发师去为一个顾客理发 
  V(mutex); //开放临界区 
  cut-hair( ); //正在理发} 
  customer() 
  { 
  P(mutex); //进程互斥 
  if (waiting) 
  { waiting := waiting+1; // 等候顾客数加1 
  V(customers); //必要的话唤醒理发师 
  V(mutex); //开放临界区 
  P(barbers); //无理发师, 顾客坐着养神 
  get-haircut( ); //一个顾客坐下等理/ } 
  else 
  V(mutex); //人满了,走吧!} 
  2.详细实现: 
  椅子数目可以设置;程序采用用随机数产生顾客进程,也就是顾客按照随机数自动到来,这样更加接近现实生活;对于理发师,当顾客到来后去理发,如果没有顾客继续看报纸,当理完一个后,判断是否有等待,有则叫下一个来理发,没有的话去看报纸。对于客人,先看理发师是空闲还是忙,空闲则去理发,忙着的话则看是否有位置等待,有则坐下等,没有的话则离开。对于理发时间,是取系统时间来控制,设理发时间为10秒,当两次时间差大于等于10时表示理完叫下一位,小于则继续理发。并且还能控制是否开门营业,当理发师为10个以上顾客理发完成并且没有人在等待时,可以决定是否关门休息. 
  代码如下: 
  #i nclude "windows.h" 
  #i nclude "iostream.h" 
  #i nclude "math.h" 
  #define random (rand()*10000)/RAND_MAX //定义一个随机函数来产生顾客,并且使两个顾客间的时间少于10秒 
  int long waiting(0); //正在等待的顾客的数目 
  int chairs; //椅子的总数目 
  char open_door; //开门 
  char close_door; //关门 
  int count(0); //顾客的号码数 
  int finish(0); //理发完毕的顾客数目 
  DWORD a; 
  void cuthair() 
  { 
  ::Sleep (10000); 
  cout<<"理发完成 !"<  } 
  void gethaircut() 
  { 
  ::Sleep (10001); //顾客被理发的函数,为了和理发师之间有所区别,比理发师理发时间长0.001秒。 
  cout<<"第"<  HANDLE barbers=::CreateSemaphore(NULL, 1,1, "barbers");//定义信号量来进行线程间的同步 
  HANDLE customers=::CreateSemaphore(NULL,0,3,"customers"); 
  DWORD WINAPI customer(LPVOID pParm2) //顾客的线程 
  { 
  ::WaitForSingleObject(Mutex ,INFINITE); //p(mutex)来进行互斥操作 
  count++; //来的是第几个顾客 
  cout<<"叮咚!第 "<  } 
  else 
  cout<<"没有人在等待"<  waiting++; 
  cout<<"还有"<  cout<<"有座位,顾客已经坐下"<  ::ReleaseSemaphore(customers,1,NULL);//v(customer) 
  ::ResumeThread(customers);//唤醒理发师进程 
  ::ReleaseMutex(Mutex);//释放互斥量,以便其他线程使用 
  ::WaitForSingleObject(barbers,INFINITE);//等待理发 
  gethaircut(); //理发并离开 
  } 
  else 
  { 
  cout<<"座位已满,第"<  ::ReleaseMutex(Mutex); 
  } 
  return 0; 
  } 
  DWORD WINAPI barber(LPVOID pParm1) //理发师的线程 
  { 
  while(true) //一直执行 
  { 
  ::WaitForSingleObject(customers,INFINITE);//p(customers),等待顾客 
  ::WaitForSingleObject(Mutex,INFINITE); //等待互斥量 
  waiting--; //等待的人数减一 
  ::ReleaseSemaphore(barbers,1,NULL); //释放信号量 
  ::ResumeThread(barbers); //唤醒顾客进程 
  ::ReleaseMutex(Mutex); //v(mutex); 
  cuthair(); //理发 
  finish++; //理发完毕的顾客数目加一 
  } 
  return 0; 
  } 
  int main(int argc, char* argv[]) 
  { 
  cout<<"请输入椅子的总数目:"; 
  cin>>chairs; 
  cout<<"理发店共有"<  cout<<"开门接待顾客吗?Y/N"<  cin>>open_door; 
  while (open_door!='y') 
  { 
  cout<  cout<<"开门接待顾客吗?Y/N"<  cin>>open_door; 
  } 
  HANDLE hThread1; 
  HANDLE hThread2; 
  hThread2=::CreateThread (NULL,0,barber,NULL,0,NULL); //产生一个理发师进程 
  while(close_door!='y') 
  { 
  ::Sleep(random); //顾客随机到来 
  hThread1=::CreateThread(NULL,0,customer,NULL,a,NULL); 
  cout<  if (finish>=10&&waiting==0) //如果完成数超过10并且没有人等待 
  { 
  cout<<"已经为"<  cin>>close_door; 
  return close_door; 
  } 
  else ; 
  } 
  if (close_door=='y') 
  { 
  cout<<"********对不起,暂停营业!********"<  return 0; 
  } 
  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值