代码改变世界

用信号量进程同步与互斥

2019-05-05 22:19  陆许  阅读(337)  评论(0编辑  收藏  举报

1.理解生产者和消费者问题

没有引入信号量时的生产者和消费者进程,什么情况下会出现结果不唯一?什么情况下会出现永远等待?

      当生产者和消费者两个进程并发执行时,会造成结果不唯一。例如此时缓冲区有n个产品,当生产者生产一个产品放入缓冲区时,此时产品数加1,同时,消费者从缓冲区取走一个产品数,产品数减1,但是两者的加或减1取决于两者的进行速度,所以缓冲区的产品数可能是n+1或者n-1,但其实正确产品数仍为n。

      当生产者和消费者两个进程交替执行时会造成永远等待。假如此时消费者认为产品数为0,那么程序调度会暂停消费者而让生产者去生产产品,生产产品则产品加1,但是由于刚才产品数为0,所以生产者会以为消费者还在睡眠,于是调用程序唤醒消费者,但其实消费者并还没有去睡眠,接收不到唤醒信号,当消费者下次运行的时候接收到的产品数仍然为0,于是去睡眠。这就产生了生产者等待消费者取走产品,消费者等待生产者生产产品,这种相互等待的过程永远不会结束,造成永久等待。

用信号解决生产者和消费者的同步与互斥,要求能自己写出来。

item B[k];

semaphore empty,full,mutex;

empty=k;full=0;mutex=1;

int in=0;

int out=0;

cobegin

        process produce(){

               while(true){

                     produce();

                     P(empty);

                     P(mutex);

                    append to B[in];

                    in=(in+1)%k;

                    V(mutex);

                    V(full);

             }

       }

       prpcess cunsumer(){

             while(true){

                   P(full);

                   P(mutex);

                   take out B[out];

                  out=(out+1)%k;

                  V(mutex);

                  V(empty);

                  consumer();

             }

      }

coend

2.哲学家吃面问题

semaphore fork[5];

     for(int i=0;i<5;i++)

          fork[i]=1;

cobegin

     process pi(){

          while(true){

                think();

                P(fork[i]);

                P(fork[(i+1)%5]);

                eat();

               V(fork[i]);

               V(fork[(i+1)%5]);

          }

     }

coend

3.读写文件问题

 

4.理发师问题

5.在一间酒吧里有三个音乐爱好者队列,第一队的音乐爱好者只有随身听,第二队只有音乐磁带,第三队只有电池。而要听音乐就必须随身听、音乐磁带和电池这三种物品俱全。酒吧老板一次出售这三种物品中的任意两种。当一名音乐爱好者得到这三种物品并听完一首乐曲后,酒吧老板才能再一次出售这三种物品中的任意两种。于是第二名音乐爱好者得到这三种物品,并开始听乐曲。全部买卖就这样进行下去。试用P,v操作正确解决这一买卖。

semaphore S,S1,S2,S3;

S=1;S1=S2=S3=0;

process 酒吧老板

begin                             

   repeat                                          

   P(S);

   售卖两样物品;

   if 售卖音乐磁带和电池 then V(S1);

   else if 售卖随声听和电池 then V(S2);

   else V(S3);

   until false

end

process 第一队

begin

   repeat

   P(S1);

   购买音乐磁带和电池;

   装备部件;

   听歌一曲;

   V(S);

   until false

end

process 第二队

begin

   repeat

   P(S2);

   购买随声听和电池;

   装备部件;

   听歌一曲;

   V(S);

   until false

end

process 第三队

begin

   repeat

   P(S3);

   购买随身听和音乐磁带;

   装备部件;

   听歌一曲;

   V(S);

   until false

end

6.某银行有人民币储蓄业务,由n个储蓄员负责。每个顾客进入银行后先取一个号,并且等着叫号。当一个储蓄人员空闲下来,就叫下一个号。请用P,V操作正确编写储蓄人员和顾客进程的程序。

semaphore customers,clerk,mutex;

customers=0;clerk=0;mutex=1;

cobegin

      process clerk(){

           while(true){

                 P(custmers);

                 P(mutex);

                 if(custmers==0)

                      constmers--;

                      V(clerk);

                      V(mutex);

                      servertime();

            }

     }

     process customers(){

            while(true){

                  P(mutex):

                  line();

                  V(mutex);

          }

    }

coend 

7.下面是两个并发执行的进程。它们能正确运行吗?若不能请举例说明,并改正之。(5分)

parbegin

    var X:integer;

    process  P1                    process  P2

    var y,z:integer:            var t,u:integer;

     begin                          begin

       x:=1;                           x:=0:

       y:=0:                           t=0;   

       if  x≥l  then y:=y十1;    if  x≤l  then  t:=t+2;

            z:=y;                           u:=t;

     end;                         end;

parend.

     因为两个进程是并发执行的,有可能出现交叉现象。假如当P1执行过程中,临界区被打断,执行P2顺利执行完成后,P1会接收到x=0的信号,而使if后面的语句无法执行;反之,P2的临界区被打断时,也只能接收到顺利执行完的P1的信号x=1,从而造成P2出错。

parbegin

    var X:integer;

    bool inside[2];

    inside[0]=false;inside[1]=false;

   enmu{0,1}   turn;

    process  P1                                             process  P2

    var y,z:integer;                                var t,u:integer;

    begin                                                       begin

         inside[0]=true;                                          inside[1]=true;

         true=1;                                                     true=0;

        while(inside[1]&&turn==1);                       while(inside[0]&&turn==0);

              x:=1;                                                      x:=0:

              y:=0;                                                      t=0;

             if  x≥l  then y:=y十1;                               if  x≤l  then  t:=t+2;

                  z:=y;                                                           u:=t;

        inside[0]=false;                                        inside[1]=false;

    end;                                                     end;

parend.

8.在一个盒子里,混装了相等数量的黑棋子和白棋子,现要用自动分拣系统把黑棋子和白棋子分开,该系统由两个并发执行的进程P1和P2组成,其中进程P1专门拣黑子,进程P2专门拣白子。规定两个进程轮流拣子且每个进程每次只拣一个子。当一个进程在拣子时不允许另一个进程去拣子,并设P1先拣。请用P,V操作管理这两个并发进程,使其能正确实现上述功能。

parbegin

    bool inside[2];

    inside[0]=false;inside[1]=false;

    enmu{0,1}   turn;

    process  P1                                             process  P2

    begin                                                       begin

         inside[0]=true;                                          inside[1]=true;

         true=1;                                                     true=0;

        while(inside[1]&&turn==1);                       while(inside[0]&&turn==0);

              拣黑子;                                                      拣白子;

        inside[0]=false;                                        inside[1]=false;

    end;                                                     end;

parend.