第五章 稍欠经典的同步问题
5.2 理发店问题
最初的理发店问题是由Dijkstra提出的。 它的变体出现在Silberschatz和Galvin的操作系统概念[10]一书中。
理发店包括一间带n把椅子的等候室和带理发椅的理发室。 如果没有顾客服务,理发师就会睡觉。 如果顾客进入理发店并且所有椅子都被占用,则顾客离开商店。 如果理发师很忙,但是椅子可用,则顾客坐在其中一把空椅子上。 如果理发师睡着了,顾客就会叫醒理发师。 编写一个程序来协调理发师和顾客。
为了使问题更具体,我添加了以下信息:
•顾客线程应调用名为getHairCut的函数。
•如果顾客线程在商店满员时到达,它可以调用不会返回的balk。
•理发师线程应该调用cutHair。
•当理发师调用cutHair时,应该只有一个线程同时调用getHairCut。
编写一个解决方案,并确保满足这些约束。
5.2.1 理发店问题提示
n是理发店能容纳的顾客总数:三个在等候室,一个在椅子上。
customers计算商店中的顾客数量; 它受互斥锁mutex保护。
理发师等待customer信号,直到顾客进入理发店,然后顾客等待barber信号,直到理发师发出信号让他坐下来。
理发后,顾客向customerDone发出信号并等待barberDone。
5.2.2 理发店问题方案
该解决方案结合了记分板和两个会合点(two rendezvouses)【复数的“会合(rendezvouses)”是罕见的,并非所有词典都理解它是什么。 另一种可能性是复数也拼写为“集合点”,但最终的“s”会发音。】。 以下是顾客的代码:
如果理发店中已有n个顾客,任何到达的顾客都会立即调用balk。 否则,每个顾客都会向customer发出信号并等待barber信号。
这是理发师的代码:
每当顾客发出信号时,理发师就会醒来,发出barber信号,然后给一个人理发。 如果另一位顾客在理发师忙碌时到达,那么在下一次迭代中,理发师将通过customer信号量而不会睡觉。
customer和barber信号量的名称都基于集合点的命名约定,因此customer.wait()表示“等待客户”,而不是“客户在这里等待”。
第二次集合,使用customerDone和barberDone,确保在理发师循环之前完成理发,让下一位顾客进入临界区。
此解决方案位于sync_code / barber.py中(参见3.2)。