一、题目描述
一个理发店有一间配有n个椅子的等待室和一个有理发椅的理发室。
如果没有顾客被服务,理发师就去睡觉。
如果顾客来时所有的椅子上都有人,那么顾客离去。
如果理发师在忙而有空闲的椅子,那么顾客就会坐在其中的一个椅子上。
如果理发师在睡觉,顾客会摇醒他。
二、实现分析
1、服务-被服务问题的消费者生产者角度解析
站在理发师的角度,顾客是生产者,理发师自身是消费者消费顾客资源
站在顾客角度,理发师是生产者,生产理发服务资源,顾客是消费者消费理发师
2、初始时:
理发师都在睡觉,理解为可用理发师semaphore barber=0;
一个顾客都没有,顾客semaphore customer=0;
一个在等待的顾客都没有,int waiting=0;
设置用于实现互斥的信号,semaphore mutex=1;
3、需要使用到PV的互斥条件:
waiting++和waiting--需要用到mutex
1)理发师角度
假设现在只有一个顾客要理发,多个理发师共同判断到了就同时让waiting--,waiting一次性被减去了多次就矛盾,所以一次只能有一个理发师实现waiting--,就相当于视顾客为资源,一次只能有一个理发师来访问这个资源
P(mutex);
if(waiting>0){//判断有没有顾客在等待理发
waiting--;//有就waiting-1进行后续操作
V(mutex);}
else{
V(mutex);
}
2)顾客角度
一个customer在理发店门口看里面等待的人满了没,如果还有空的座位,即waiting<n,则他就进去占用一个等待位waiting++,但是这个判断一次只能一个customer判断,否则假设5个顾客同时判断waiting=n-1<n,那都同时以为自己可以进店,同样都将占用这最后一个空位,但是这个空位只能容纳一个人所以就产生了冲突,需要在if(waitng<n) waiting--前后加P(mutex)和V(mutex),这样一次只能有一个顾客判断,则mutex=1-1=0,其余的顾客阻塞在P(mutex),只有当这个顾客执行完V(mutex)释放了mutex,mutex=0+1=1;,下一个顾客才可再次进行判断。
P(mutex);
if(waiting<n){
waiting++;
V(mutex);
}else{
V(mutex);
}
三、伪代码实现
semaphore barber=0;
semaphore customer=0;
semphore mutex=0;
int waiting =0;
parbegin
progress customer(){
P(mutex);
if(waiting<n){
waiting++;
V(mutex);
V(customer);
P(barber);
have_hair_cut();
}else{
V(mutex);
}
progress barber(){
while(1){
P(mutex);
if(waiting>0){
waiting--;
V(mutex);
V(barber);//唤醒理发师
cut_hair();
}else{
V(mutex);
P(customer);//这样如果没顾客的话就一直阻塞在这步,barber就不会一直进入while(1)循环忙等
}
}
parend;