第二章 进程的描述与控制(2)


2.4经典同步问题


一、生产者——消费者问题(互斥、同步)
生产者与生产者,消费者与消费者之间是互斥的关系。生产者与消费者之间是顺序关系。
设置信号量empty,full以及互斥信号量mutex设初值为1。
(1)两个生产者同时的情况:
producer :
int in=0,out=0;
item buffer[n];
semaphore mutex=1,empty=n,full=0;
void producer(){
do{

produce an item in nexp;

wait(empty);//先执行对资源的信号量的操作然后进行对互斥信号量的操作。操作顺序不可颠倒防止进程死锁。
wait(mutex);
buffer(in):=nexp;
in:=(in+1) mod n;
signal(mutex);//信号量成对的出现
signal(full);
}while(true);
}
过程分析:
1)1号生产者的wait操作使e=n-1,m=0
2)当1号正在in=0的buffer[0]放入产品时,2号来到,wait(e)仍通过,e=n-2;但wait(m)会使2号阻塞。m=-1,e=n-2。
3)转入1号生产者执行使in=1,,唤醒m上的等待者——2号生产者,但可能并不立即切换到2号运行,而是其分到的cpu时间完成后再转到2号。此时m=0,f=1。
4)回到2号进程后,将产品放入缓冲区;in=2;m=1;f=2。
(2)生产者等待消费者的情况
produce;
wait(e);
wait(m);
buffer(in):=nexp;
wait(f);
wait(m);
nextc:=buffer(out);
in:=(in+1)mod n;
signal(m);
signal(f);
out:=(out+1) mod n;
signal(m);
signal(e);
consume;
过程分析:
1)设当前运行到一个临界点,缓冲区满了,而生产者先来了要生产。
2)e=0;m=1;f=n当第一个生产者来了,e=-1被阻塞,只有等到一个消费者来时程序才可以继续。此时wait(f),f=n-1,wait(m),m=0,继续向下执行,执行过后signal,m=1,f=n。
3)out:=(out+1) mod n,取出产品,当signal(m),m=2;signal(e),e=0.
注意:signal原语唤醒的因wait阻塞的进程后该进程并不需再重新执行wait。
(3)2个生产者2个消费者在这里插入图片描述
AND信号量的方式
consumer :
repeat
Swait(full,mutex);
nextc:=buffer(out);
out:=(out+1) mod n;
Ssignal(mutex,empty);
consume the item in nexc;
until false;
二、哲学家就餐问题(互斥)
筷子是临界资源,要实现对筷子的互斥相邻两位不能同时进餐;最多只能有两人同时进餐。
解决方案:
(1)至多只允许有四位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐,并在用毕后释放出他用过的两只筷子,从而使更多的哲学家能够进餐。
第i 位哲学家的活动可描述为:
repeat
wait(chopstick[ i ]);
wait(chopstick[ ( i +1) mod 5] );

eat;

signal(chopstick[ i ]);
signal(chopstick[ ( i +1) mod 5] );

think;
until false;
(2)仅当哲学家的左右两只筷子均可用时,才允许他拿起筷子进餐。—采用AND信号量
Var chopstick: array [0, …, 4] of semaphore:=(1, 1, 1, 1, 1);
Process i
repeat
think;
Swait(chopstick[ ( i +1) mod 5] , chopstick[ i ] );
eat;
Ssignal(chopstick[ ( i +1) mod 5] , chopstick[ i ] );
until false;
(3) 规定奇数号哲学家先拿他左边的筷子,然后再去拿右边的筷子;偶数号哲学家则相反。保证总会有一个哲学家能同时获得两只筷子而进餐。—采用IF编程控制
三、读者——写者问题(有条件的互斥)
Writer进程与任何其他进程(包括Reader进程或其他Writer进程)不允许同时访问文件。
(1)写者操作要和其他的都互斥,所以必要判断互斥信号量, 没有变化:
(2)只有第一个读进程进行互斥判断;
(3)只要有一个“读进程”在读就不释放,“写进程”就不能写。(一种读者优先的方式

写者Writer :
repeat
wait(wmutex);
写入文件;
signal(wmutex);
until false;
读者Reader :
begin
repeat
wait(rmutex);
if Readcount=0 then wait(wmutex);//防止写进程再进入,不影响其他读进程
Readcount :=Readcount +1;
signal(rmutex);

perform read operation;

wait(rmutex);
Readcount :=Readcount -1;
if Readcount=0 then signal(wmutex);
signal(rmutex);
until false;
end
写者优先的方式
在这里插入图片描述读者间起作用:
Readcount变量,rmutex信号量
写者间起作用:
writecount变量,mutex信号量
读者与写者间起作用:
wmutex
S
四、黑白棋子问题
两种情况的解决办法:
(1)执黑子一方先下
信号量:b=1,w=0;
黑:
while(没结束){
wait(b);
下一黑棋;
signal(w);
}
白:
while(没结束){
wait(w);
下一白棋;
signal(b);
}
另一种方式:
semaphore bfg=1;wfg=0;
void main(){
black();white();
void black(){
while(true){
wait(bfg);
if whereput(){
put a black chess;
}
else break;
signal(wfg);
}
}
void white(){
while(true){
wait(wfg);
if whereput(){
put a white chess;
}else break;
signal(bfg);
}
}
}
(2)双方都可以先下,谁先抢到棋盘谁先下。然后开始轮流下子。
利用互斥信号量与特殊标志变量的结合使用实现有序控制
semaphore bfg=1;wfg=0;m=1;
boolean fg=F;
void main(){
black();
white();
}
void black(){
wait(m);
if !fg{
bfg=1;wfg=0;fg=T;
signal(m);
while(true){
wait(bfg);
if whereput(){
put a black chess;
signal(wfg);
}
else{
signal(wfg);
break;
}}}
void white(){
wait(m);
if !fg{
bfg=0;wfg=1;fg=T;
}
signal(m);
while(true){
wait(wfg);
put a white chess;
signal(bfg);
}}
五、嗜睡的理发师问题

Int cout=0;        
Semaphore mutex=1,sofa=N,empty=1,full=0,cut=0,payment=0,receipt=0;       process guesti() 顾客i              
 {   wait(mutex);  //count既用于判断,也要修改,所以为临界资源,用mutex管理互斥,但由于是分支结构,所以要在每个分支结构中注意离开count的临界区时使用signal释放临界资源            
 if(count>N)// 沙发中已经坐满客人N个和正在理发的1位,没有沙发,客人离开理发店  {signal(mutex); exit shop; }             
 else                 
 { count=count+1;                  
  if(count>1)  //count>1,意味着原来理发店里有客人,所以不能坐理发椅,需要坐到沙发上等待                    
  { signal(mutex); 
  wait(sofa);       //申请沙发,肯定能得到                      
  sit on sofa;                      
  wait(empty);      //申请理发椅,等不到阻塞,得到,则从沙发上站起,准备坐到理发椅上                      
  get up form sofa;                     
   signal(sofa);       //归还沙发 
    }                 
     else                    
      { signal(mutex);   
      wait(empty);     //count==1,意味着这个店里只有这一个顾客,他不必要申请沙 发,直接申请理发椅即可 
       }                   
        sit on the baber_chair;                    
        signal(full);    //若理发师阻塞,则唤醒理发师,若未阻塞,则将full由0增1,理发师申请理发时即可通过                    
         wait(cut);      //测试理发是否完成,没有则阻塞                   
         pay;                        
         signal(payment);  //若理发师阻塞,则唤醒理发师告知其已经付费,若未阻塞,则将paymentl由0增1,理发师申请理要求付费时即可通过                   wait(receipt);     // //测试理发师收费是否完成,没有则阻塞                    
   get up form the baber_chair;  //理发师收费完成,顾客离开理发椅                  signal(empty);    //释放理发椅                      wait(mutex);      //对count 临界资源操作,用mutex完成互斥                   count=count-1;                   
   signal(mutex);                   
   exit shop;  }              
   }          
    process barber( )           
     { while(1)               
      {wait(full);    //测试理发椅上是否有顾客,无则阻塞                
      cut hair;                 
      signal(cut);    //告知顾客理发完成               
       wait(payment);  //测试顾客是否付费                
       accept pament;                 
       signal(receipt);  //告知顾客收费完
                      }             
                      }         
                       main( )         
                        {cobegin              
                         { guesti();               
                          Barber();              
                          }          
                           }

猜你喜欢

转载自blog.csdn.net/weixin_43270792/article/details/82859440