传送门:
进程同步与互斥——哲学家就餐问题源码实现(dining philosopher’s problem)
进程同步与互斥——读者/写者问题源码实现(reader-writer lock)
进程同步与互斥——吸烟者问题源码实现(cigarette smoker’s problem)
进程同步与互斥——理发师问题源码实现(sleeping barber problem)
理发师问题描述:
(1)理发店里有一位理发师、一把理发椅和n把供等候理发的顾客坐的椅子
(2)如果没有顾客,理发师便在理发椅上睡觉
(3)一个顾客到来时,它必须叫醒理发师
(4)如果理发师正在理发时又有顾客来到,则如果有空椅子可坐,就坐下来等待,否则就离开
问题分析:
1、对于理发师问题而言,是生产者-消费者(有界缓冲区)模型的一种。其中理发师和顾客之间涉及到进程之间的同步问题,理发师是生产者,顾客是消费者,生产者生产的速度(理发师理发的速度),和消费者消费的速度(顾客来到理发店的时间),这两者肯定是不同的。那么,题目中就涉及到了一个有界缓冲区,即有N把顾客可以坐着等候理发师的椅子。如果顾客来的太快了,就可以先坐在椅子上等候一下理发师,但是如果椅子坐满了,这时候顾客就直接走,不理发了。这个N是有界缓冲区的大小,如果缓冲区放不下消费者了,消费者就不进行消费。
2、同样的,在生产者-消费者(有界缓冲区)模型中,还存在进程之间的互斥,比如多个消费者同时访问缓冲区,那么肯定会改变缓冲区的状态,缓冲区就是临界资源,多个消费者不能同时去改变缓冲区的状态。在这个问题上,就相当于执行顾客任务的进程,就必须有互斥的操作,同样的,理发师改变缓冲区状态的操作也需要互斥。这个问题中,缓冲区的状态,就是还剩多少个在等待的顾客,顾客来一个,肯定等待理发的顾客数目就+1,理发师理一次发,等待理发的顾客数目就-1。
我们先确定初始状态,即:
顾客没来的时候理发师正在睡觉,刚开始也没有顾客来:
semaphore barbers = 0;
semaphore customers = 0;
顾客之间被理发的时候,也需要一个互斥量:
semaphore mutex = 1;
初始化有界缓冲区的大小是N,即
#define CHAIRS 5
另外,我们还需要一个变量来记录目前缓冲区的大小是多少,看现在正在等待的顾客数量有没有超过缓冲区的大小,如果超过了,顾客就之间转身走了。
int waiting = 0;
以上,初始化的操作已经完成了。
#define CHAIRS 5
semaphore customers = 0;
semaphore barbers = 0;
semaphore mutex = 1;
int waiting = 0;
然后,考虑理发师进程需要执行的任务,首先理发师是不断进行理发操作的,只有一个生产者,所以肯定对任务有while(1)让它不断执行的操作。
在单次任务中,理发师先等待顾客,如果顾客没有来,理发师就在睡觉。
P(consumers);
然后,如果等到了一个顾客来了,理发师就要更新缓冲区状态了,把正在等待理发的顾客数目-1,先进行加锁互斥。
P(mutex);
waiting = waiting - 1;
然后理发师睡起来了,准备开始理发了。
V(barber);
因为理发操作,所需花费的时间是很长的,这里不能放在临界区去执行。理发师理发前,先解锁,离开临界区。
V(mutex)
cut_hair();
那么,理发师进程需要执行的任务,我们就可以写出来了:
void barber(void)
{
white (TRUE) {
P(customers); //若无顾客,理发师睡眠
P(mutex); //进程互斥,要求顾客等候
waiting = waiting − 1; //等候顾客数少一个
V(barbers);

本文探讨了理发师问题的进程同步与互斥解决方案,通过信号量和互斥量实现理发师与顾客间的协调,模拟生产者-消费者模型。涉及的任务分解、互斥操作及有界缓冲区的使用,提供了详细的伪代码和C++实现示例。
最低0.47元/天 解锁文章
2960





