用信号量进程同步与互斥

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

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

结果不唯一:假如当前的产品数为8,如果生产者生产一件产品投入缓存区,拟执行产品数加一操作;同时消费者取走一样产品,拟执行产品数减一操作;假如两者交替执行加一或减一操作,取决于其执行速度,产品数为9或7,但正确为8.

永远等待:假如消费者读取产品数为0时,调度程序暂停消费者进程,让生产者进程运行,生产者加入一个产品,将产品数加一,它便调用wakeup()函数来唤醒消费者;但是消费者未睡眠,则唤醒信号丢失,当消费者下次运行时,因已检测到产品数为0,于是去睡眠,当生产者将缓冲区填满后也去睡眠,这就会造成永远等待。

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

int k;

typedef anyitem item;

item buffer[k];

int i=0,out=0,counter=0;

process producer(void){

        while(ture)  {

              {produce an item in nextp};

              if(counter==k)

                    sleep(producer);

              buffer[in]=nextp;

              in=(in+10)%k;

              counter++;

              if(counter==1)

                   wakeup9consumer);} }

processconsumer(void){

          while(ture) {

               if(counter==0)

                       sleep(consumer);

                       nextc=buffer[out];

                       out=(out+1)%k;

                       counter--;

                       if(counter==k-1)

                             wakeup(producer);

                        {consume the item in nextc} ;  }  }

 

2.哲学家吃面问题

semaphore fork[5];

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

                                fork[i]=1;

                      cobegin

                            process philosopher_i( ){

                                       while(ture){

                                                      think( );

                                                       P(fork[i]);

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

                                                                eat();

                                                       V(fork[i]);

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

                                                            }

                                           }

coend

 

3.读写文件问题

int readcount=0;

semaphore writeblock=1,mutex=1;

cobegin

process reader_i() {

         P(mutex);

       readcount++;

        if(readcount==1)

          P(writerblock);

          V(mutex);

          /*读文件*/

         P(mutex);

         readcount--;

         if(readcount==0)

                  V(writeblock);

           V(mutex);  }

coend

 

4.理发师问题

int waiting=0, chairs=n;

semaphore customers=0,barbers=0,mutex=1;

cobegin

     process barbers() {

           while(ture) {

                P(customers);

                P(mutex);

                waiting--;

                V(barbers); 

                V(mutex);

                cuthair();  } }

process customer_i() {

               P(mutex);

               if(waiting<chairs) {

                     waiting++;

                      V(customers);

                       V(mutex);

                       P(barbers):

                       get_haircut();

}

else

        V(mutex);

}

coend

                       

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

 

semaphore mutex=1,p=1, p1=0, p2=0, p3=0;

process p(){

    while(ture){

        p(p);

       p(mutex);

        老板任意出售两种;

        if(出售音乐磁带和电池) v(p1);

        if(出售随身听和电池)  v(p2);

        else v(p3); 

        v(mutex);  } }

process p1() {

        while(ture){

         p(p1);

         p(mutex);

        listening();

       v(mutex);

        v(p);  } }

process p2() {

        while(ture){

         p(p2);

         p(mutex);

         listening();

        v(mutex);

        v(p);  } }

process p3() {

        while(ture){

         p(p3);

         p(mutex);

         listening();

        v(mutex);

        v(p);  } }

 

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

 semaphore customers=0,clerk=0,mutex=n;

int waiting=0;

cobegin

  process clerk() {

                   while(ture){

                            P(customers);

                            P(mutex);

                            waiting--;

                            V(clerk);

                            V(mutex);

                             service();

} }

process customer_i() {

                     P(mutex);

                    waiting++;

                    V(customers);

                       V(mutex);

                       P(clerk):

                       get_service();

}

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结果是:x=0y=1z=1t=2u=2。 若先执行P1到x:=1;然后一个中断去执行完P2再一个中断回来执行完P1结果是:x=0y=0z=0t=2u=2。

 改正:

parbegin

var x:integer; var s:semaphore:=1;

process P1                                   process P2

       var y,z:integer ;                             var ,tu:integer ;

begin                                           begin

      P(s);                                           P(s);

      x:=1;                                         x:=0;

      y:=0;                                         t:=0;

        if x>=1 then y:=y+1;                   if x<=1 then t:=t+2

      V(s);                                            V(s);

         z:=y;                                           u:=t;

end                                                end

parend

 

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

semaphore s1=1,s2=0;

cobegin {

      process P1

         begin

            repeat

                P(s1);

                 拣黑子;

                V(s2);

              until false;

           end

  process P2

         begin

            repeat

                P(s2);

                 拣白子;

                V(s1);

              until false;

           end

}

coend

 

 

posted @ 2019-04-30 22:07  星瘾  阅读(342)  评论(0编辑  收藏  举报