PV操作实现进程同步问题

1.设玩具车间生产小组在一个工作台边工作,工作台上有N个位置(N≥3)用于存放车架或车轮,且每个位置只能放一件车架或车轮;又设生产小组有3个工人,其活动分别为:
工人1活动:
do
{加工1个车架;车架放于工作台上;}
while (1)
工人2活动:
do
{加工1个车轮;车轮放于工作台上;}
while (1)
工人3活动:
do
{从工作台上取1车架;从工作台上取2车轮;组装为一辆车;}
while (1)
试用信号量与P、V操作实现三个工人的合作,要求解中不含死锁。
先定义信号量:为防止死锁的发生,工作台中车架的数量不可超过 N-2,车轮的数量不可超过N-1,这些限制可以用两个信号量来表达。
semaphore s1=N-2; semaphore s2=N-1; (2分)
其余信号量:frame=0为车架数量;wheel=0为车轮数量;empty=N为工作台上的空位
(2分)
不含死锁的解法如下:在相应位置添加PV操作

工人 1活动:( 3分)
do {
 加工1个车架 ; 
P(s1); P(empty);
车架放入工作台中 ; V(frame); 
} while (1)  
工人 2活动:( 3分)
do {
 加工1个车轮 ;
 P(s2);
 P(empty);
 车轮放入工作台中 ;  V(wheel); 
} while (1)    
工人 3活动:(6分)
do {
 P(frame);                  
从工作台中取1车架 ; 
V(empty); V(s1);
P(wheel); P(wheel); 
从工作台中取2车轮 ; 
V(empty); V(empty); 
V(s2); V(s2);
 组装为1台车 ; 
} while (1) 

2.某银行提供一个服务窗口和10个供顾客等待的座位。顾客到达银行时,若有空座位,则到取号机上领取一个号,等待叫号。取号机每次仅允许一个顾客使用。当营业员空闲时,通过叫号选取一位顾客,并为其服务。顾客及营业员的活动描述如下:
cobegin
{ process 顾客
{
从取号机获取一个号码;
等待叫号;
获得服务;
}
process 营业员
{
while(TRUE)
{
叫号;
为顾客服务;
}
}
}coend
请添加必要的信号量和P、V(或wait()、signal())操作,实现上述过程中的互斥与同步。要求写出完整的过程,说明信号量的含义并赋初值。

semaphore mutex=1;   //互斥使用取号机
semaphore empty=10;     //空座位的数量	
semaphore full=0;     //已占座位的数量,必须大于0营业员才可以开始服务
semaphore service=0;        //等待叫号
cobegin
{
process 顾客i
{
P(empty);	
    P(mutex);
从取号机获得一个号;
V(mutex);
V(full);
P(service);           // 等待叫号
}
process 营业员
{
while(TRUE)
{
   P(full);
   V(empty);
   V(service);          //叫号
   为顾客服务;
   }
}
}
coend

3.多个进程共享一个文件,其中只读文件的称为读者,只写文件的称为写者。读者可以同时读,但写者只能独立写。试(1)用P、V操作写出其同步算法。(2)修改上述的同步算法,使得它对写者优先,即一旦有写者到达,后续的读者必须等待。
一个读者进程发现有其它读者在读时,不用对write进行PV操作
(1)

semaphore  mutex=1;            4分
semaphore  write=1;
int count=0;
main()     
{    cobegin
        reader();
        writer();
    coend  }
reader()
{    while(true)
    {   p(mutex); //mutex是对count上锁,对count进行加减前需要P操作,加减后需要V操作
        if(count==0) p(write);        
        count ++;
        v(mutex);
        读文件;
        p(mutex);
        count -- ;
        if (count==0) v(write);
        v(mutex);    }   }
writer()
{    while(true)
    {   p(write);
        写文件;
        v(write);    }   }

(2)6分:

semaphore  mutex=1;  
semaphore  write=1;
semaphore  s=1;  //设为1
int count=0; 
main()
{    cobegin
        reader();
        writer();
    coend  }
reader()
{    while(true)
    {   p(s);
        p(mutex);
        if(count==0) p(write);
        count ++;
        v(mutex);
        v(s);
        读文件;
        p(mutex);
        count -- ;
        if(count==0) v(write);
        v(mutex);    }   }
writer()
{    while(true)
    {   p(s);
        p(write);
        写文件;
        v(write);
        v(s);    }   }

4.利用 P、V 原语,形式化或非形式化地描述下列进程的动作序列。( 8 分) 进程 P 使用缓冲区 B 向 m 个进程 Q1、Q2、…、Qm 发送消息,要求每当 P 向 B 中发送一 条消息,只有当所有的进程 Q(=1,2,…,m,) 都读取这条消息后,P 才向 B 中发送新的消息。
在这里插入图片描述
设 s 为缓冲区的用信号量,初值为 s=1;
设 s1 表示缓冲区是否有空间存放消息,初值为 s1=1;
设一个信号量数组 T[i](I=1,2,…m), 初值为 T[i]=0; (表示 Qi 是否有消息可读)
设一个计数器 R(初值为 0)用来统计读取消息的进程数目

P 进程:                
P(s1)                   
P(s)                     
存放消息至缓冲区        
R=m                  
FOR i=1 to m do V(T[i])    
V(s)        
Q进程:
P(T[i]) 	
P(s)
取得该消息
 R=R-1 
 IF  R=0  then  V(s1)
 V(s) 

因为Q1~Qm都不同,所以不能简单用一个计数器,还要设置一个信号量数组
给计数器R上锁?

5.在读者写者问题中,读者优先策略使得后到达的读者可能先于写者访问数据文件,那么如何为写者进行改进,而使其不会出现饥饿的现象呢?这里增加了一个排序队列queue,所有读者写者都需在此队列排队,然后依次访问数据文件,即公平竞争。请填充写者程序中空白处的wait和signal操作。

Semaphore fmutex=1, rdcntmutex=1, queue=1;   int readcount = 0;
//fmutex --> access to file; rdcntmutex --> access to readcount
void reader(){
    while(1){
        wait(queue);
        wait(rdcntmutex);
        if(0 == readcount)wait(fmutex);
        readcount = readcount + 1;
        signal(rdcntmutex);
        signal(queue);
        //Do read operation ...
        wait(rdcntmutex);
        readcount = readcount - 1;
        if(0 == readcount)signal(fmutex);
        signal(rdcntmutex);
    }
}	void writer(){
    while(1){
           (1) wait (queue)   ;
           (2) wait (fmutex)   ;
           (3) signal (queue)   ;
        //Do write operation ...
           (4) signal (fmutex)   ;
    }
}

6.一座最多只能承受两个人的小桥横跨南北两岸,任意时刻同一方向只允许一人过桥,南侧桥段和北侧桥桥段较窄只能通过一人,桥中央一处宽敞,允许两个人通过或歇息。试用信号量和P、V原语写出南、北两岸过桥的同步算法。
因为南北两侧桥段都只能一人通过,所以要分别设两个信号量,通过之前都要P一下,通过之后V一下

Semaphore load=2;  //定义初值1分  
//也可以设两个信号量fromsouth, fromnorth都为1,代表从一个方向过桥的人数
Semaphore north=1;                 
Semaphore south=1;
main()
{  cobegin
    tosouth();    tonorth();     1分
   coend  }
tosouth()   2分
{
P(load);
P(north);
走过桥北半段到桥中央;
V(north);	
P(south)
走过桥南半段;
V(south);
V(load);
}
tonorth()          2分
{
P(load);
P(south);
走过桥南半段到桥中央;
V(south);
P(north)
走过桥北半段;
V(north);
V(load);
}

7.独木桥问题。某条河上只有一座独木桥,以便行人过河。现在河的两边都有人要过桥,按照下面的规则过桥。为了保证过桥安全,请用P、V操作分别实现正确的管理。
过桥的规则是:同一方向的可连续过桥,某方向有人过桥时另一方向的人要等待。
本题中使用三个信号量:
mutexl、mutexr用于互斥访问共享变量countl及countr,初值均为1。
wait用于申请过桥,初值也为1。

同步算法描述如下:

semaphore mutexl=1;
semaphore mutexr=1;
semaphore wait=1;
int countl=0;
Int countr=0;
main()
{ cobegin
     passl();
     passr();
   coend}
passl()
{  P(wait);   P(mutexl);
   countl++;
   if(countl==1)P(mutexr);
   V(mutexl);   V(wait);
   过河;
   P(mutexl);	
   countl- -;
   if(countl==0)V(mutexr);
   V(mutexl);}
passr()
{  P(wait);   P(mutexr);
   countr++;
   if(countr==1)P(mutexl);
   V(mutexr);   V(wait);
   过河;
P(mutexr);
   countr- -;
   if(countr==0)V(mutexl);
   V(mutexr);}

8.一个快餐厅有4 类职员:①领班:接受顾客点菜;②厨师:准备顾客的饭菜;③打包工:将做好的饭菜打包;④出纳员:收款并提交食品。每个职员可被看作一个进程,试用一种同步机制写出能让四类职员正确并发运行的程序。
本题中使用4个信号量:
S1表示是否可以开始点菜,初值为1
S2表示是否可以开始做菜,初值为0
S3表示是否可以开始打包,初值为0
S4表示是否可以提交食品,初值为0

同步算法描述如下:

semaphore S1=1;
semaphore S2=0;
semaphore S3=0;
semaphore S4=0;
main()
{ cobegin
     LB();
     CS();
     DBG();
     CNY();
   coend}
LB() 
{   while(true)
    {
       顾客到达;
       p(S1);
       接受顾客点菜;
       v(S2)}     }
CS() 
{   while(true)
    {
       p(S2);
       准备顾客的饭菜;
       v(S3)}     }
DBG() 
{   while(true)
    {
       p(S3);
       打包顾客的饭菜;
       v(S4)}     }
CNY() 
{   while(true)
    {
       p(S4);	
       收款并提交食品;
       v(S1)}     }

9.设公共汽车上,司机和售票员的活动分别如下:
①司机的活动:启动车辆:正常行车;到站停车。
②售票员的活动:关车门;售票;开车门。
在汽车不断地到站、停车、行驶过程中,这两个活动有什么同步关系?用信号量和P、V 操作实现它们的同步。
在本题中,应设置两个信号量:s1、s2,
s1表示是否允许司机启动汽车,其初值为0;
s2表示是否允许售票员开门,其初值为0。

用P、V原语描述如下:

semaphore s1=0;
semaphore s2=0;
main( )
{
cobegin
  driver( );
  busman( );
coend
}
driver( )
{  while (true)
   {
        p(s1);
       启动车辆;
       正常行车;
       到站停车;
       v(s2);   }
}
busman( )
{   while(true)
    {
        关车门;
        v(s1);
        售票;
        p(s2);
       开车门;
       上下乘客;  }
}

10.有一只铁笼子,每次只能放入一只动物。猎手向笼中放入老虎,农民向笼中放入猪;动物园等待取笼中的老虎,饭店等待取笼中的猪。请用P、V原语写出这四个进程同步执行的程序。
在本题中,应设置三个信号量
信号量Scage表示笼子是否为空,其初值为1 (实现互斥)
信号量Spig表示笼中是否有猪,其初值为0 (实现同步)
信号量Stiger表示笼中是否有老虎,其初值为0

同步描述如下:

semaphore  Scage=1;  
semaphore  Stiger=0;
semaphore  Spig=0;
main( )
{  cobegin
     hunter( );
     peasant( );
     hotel( );
     zoo( );
  coend    }
hunter( )
{     while (true )
      {
            ┆
         p(Scage);
         将老虎放入笼中;
          v(Stiger)}   }
peasant( )
{     while (true )
      {
           ┆
         p(Scage);
         将猪放入笼中;
          v(Spig)}    }
hotel(  )
{     while( true )
       {
          p(Spig);
          从笼中取出猪;
          v(Scage);
             ┆
        }    }
zoo( )
{     while( true )
       {
          p(Stiger);
          从笼中取出老虎;
          v(Scage);
            ┆
        }   }

11.今有三个并发进程R、M、P,它们共享了一个可循环使用的缓冲区B,缓冲区B共有N个单元。进程R负责从输入设备读信息,每读一个字符后,把它存入到缓冲区B的一个单元中;进程M负责处理读入的字符,若发现读入的字符中有空格符,则把它改成“,”;进程P负责把处理后的字符取出并打印输出。当缓冲区单元中的字符被进程P取出后,则又可用来存放下一次读入的字符。请用P、V操作为同步机制写出它们能正确并发执行的程序。
在本题中,应设置四个信号量mutex、empty、full1、full2。
mutex用于实现对缓冲区的互斥访问,其初值为1;
empty表示缓冲区中可用单元数目,其初值为N;
full1表示已读入字符个数,其初值为0;full2表示已处理字符个数,其初值为0。
为了描述方便起见,还应设置三个指针in、out1、out2,
in指向下一个可用缓冲单元,
out1指向下一个待处理字符,
out2指向下一个待输出字符。

semaphore  empty=N;semaphore  full1=0;
semaphore  full2=0;semaphore  mutex=1;
char buffer[N];
int in=0,out1=0,out2=0;
main()
{  cobegin
     R();
     M();
     P();
   coend     }
R() 
{   while(true)
    {  char x;
       读入一个字符到x;
       p(empty);
       p(mutex);
       buffer[in]=x;
       in=(in+1)% N;
       v(mutex);
       v(full1)}     }
M() 
{    char x;
     while(true)
      {  p(full1);
          p(mutex);
          x=buffer[out1]if (x==" ")  {   x=“,”;
                               buffer[out1]=x;   }
          out1=(out1+1)% N;
          v(mutex);
          v(full2)}    } 
P() 
{  char x;
    while(true)
      { p(full2);
         p(mutex);
         x=buffer[out2];
         out2=(out2+1)% N;
         v(mutex);
         v(empty);
         输出字符x;
      }     }

12.下图给出了5个进程合作完成某一任务的前趋图,试用P、V操作描述它。
在这里插入图片描述

semaphore  f1=f2=f3=f4=0;   1分
main()
{  cobegin
    S1();    S2();    S3();    S4();    S5();     1分
   coend  }
S1()                                      下面共8分
{    执行代码;
     v(f1);
     v(f1);
}
S2()
{    执行代码;
     v(f2);
}
S3()
{    p(f1);
     执行代码;
     v(f3);
}
S4()
{    p(f1);
     p(f2);
     执行代码;
     v(f4);
     }
S5()
{    p(f3);
     p(f4);
     执行代码;
     }
  • 11
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值