用C#模拟“嗜睡的理发师”问题

时间:2022-05-06 00:14:13

        近日,一直在思考操作系统老师留给我们的一个进程同步问题。

        问题是这样的:一个理发店由一个有N张沙发的等待室和一个放有一张理发椅的理发室组成。没有顾客要理发时,理发师便去睡觉。当一个顾客走进理发店时,如果所有的沙发都已被占用,他便离开理发店;否则,如果理发师正在为其他顾客理发,则该顾客就找一张空沙发坐下等待;如果理发师因无顾客正在睡觉,则由新到的顾客唤醒理发师为其理发。在理发完成后,顾客必须付费,直到理发师收费后才能离开理发店。试用信号量实现这一同步问题。并编写一程序进行模拟。

        因为刚学过进程管理这一内容。用信号量实现并不困难。

        分析可知:顾客进程和理发师进程之间存在着多种同步关系:

        (1)只有在理发椅空闲时,顾客才能坐到理发椅上等待理发师理发,否则顾客便必须等待;只有当理发椅上有顾客时,理发师才可以开始理发,否则他也必须等待。这种同步关系类似于单缓冲(对应于理发椅)的生产者——消费者问题中的同步关系,故可通过信号量empty和full来控制。

        (2)顾客理完发后必须向理民师付费,并等理发师收费后才能离开,而理发师则需等待顾客付费,并在收费后通知顾客离开,这可分别通过两个信号量payment和receipt来控制。

        (3)等候室中N张沙发是顾客进程竞争的资源,故还需要为它们设置一个资源信号量sofa。

        (4)为了控制顾客人数,使顾客能在所有的沙发都被占用时离开理发店,还必须设置玫个整型变量count来外处理理发店中的顾客进行计数,该变量将被多个顾客进程互斥地访问并修改,这可通过一个互斥信号量mutex来实现。

        所以为解决这一问题,需要设置一个整型变量count用来对理发店中的顾客进行计数,并需设置6个信号量。其中:mutex用来实现顾客进程对count变量的互斥访问,其初值为1;sofa是对应于等待室中N张沙发的资源信号量,其初值为N;empty表示是否空闲的理发椅,其初值为1;full表示理发椅上是否坐有等待理发的顾客,其初值为0;payment用业等待付费,其初值为0;receipt用来等待收费,其初值为0;具体的算法描述如下:

        var count:iteger=0;

                mutex,sofa,empty,full:semaphore:=1,N,1,0;

                cut,payment,receipt:semaphore:=0,0,0;

        begin

            parbegin

                guest:begin

                                  wai(mutex);

                                  if(count>N) then

                                  begin

                                      signle(mutex);

                                      离开理发店;

                                  end

                                  else

                                  begin

                                      count:=coun+1;

                                      if(count>1) then

                                      begin

                                          wait(sofa);

                                          在沙发中就坐;

                                          wait(empty);

                                          从沙发上起来;

                                          signal(sofa);

                                      end

                                      else /* count=1 */

                                          wait(empry);

                                      在理发椅上就坐;

                                      sinal(full);

                                      理发;

                                      付费;

                                      sinal(payment);

                                      wait(receipt);

                                      从理发椅上起来;

                                      signal(empty);

                                      wait(mutex);

                                      count:=count-1;

                                      signal(mutex);

                                      离开理发店;

                                  end

                          end

                barber:begin

                                  repeat

                                      wait(full);

                                      替顾客理发;

                                      wait(payment);

                                      收费;

                                      sinal(receipt);

                                  untile false;

                            end

          parend

        end

        算法出来了,但现在问题是如何用程序来模拟呢?

        因为我们对C#语言比较熟悉,所以首先想到设计一个windows应用程序来模拟。在C#中命各空间System.Threading定义了许多有关线程同步和互斥的类和方法。但具体该怎样使用我还不得要领,思考中……