操作系统PV操作的几个例子
操作系统PV操作的几个例子
操作系统中PV操作的几个例子
题1:面包师有很多面包,由n个销售人员推销。每个顾客进店后取一个号,并且等待叫号,当一个销售人员空闲下来时,就叫下一个号。试设计一个使销售人员和顾客同步的算法。
思路:顾客进店后按序取号,并等待叫号,销售人员空闲之后也是按序叫号,并销售面包。因此同步算法只要对顾客取号和销售人员叫号进行合理的同步即可。我们使用两个变量i和j分别记录当前的取号值和叫号值,并各自使用一个互斥信号用于对i和j的访问和修改
代码:
int i=0,j=0;
semaphore mutex_i=1,mutex_j=1;
Consumer()
{
//进入面包店
p(mutex_i);
//取号i
i++;
v(mutex_i);
//等待叫号i并购买面包
}
Seller()
{
while(1)
{
p(mutex_j);
if(j<i) //号 j 已有顾客取走并等待
{
//叫号 j
j++;
v(mutex_j);
//销售面包
}
else
{
v(mutex_j);
//休息片刻
}
}
}
题 2:三个合作进程 P1,P2,P3,它们都需要通过同一设备输入各自的数据 a,b,c,该输入设备必须互斥地使用,而且其第一个数据必须有 P1 进程读取,第二个数据必须由 P2 进程读取,第三个数据必须由 P3 进程读取。然后三个进程分别对输入数据进行下列计算:
P1:x=a+b;
P2:y=a*b;
P3:z=y+c-a;
最后 P1 进程通过所连的打印机将结果 x,y,z 的值打印出来,请用信号量实现他们同步。
思路:为了控制三个进程依次使用输入设备进行输入,需分别设置三个信号量 S1,S2,S3,其中 S1 初值为 1,S2 和 S3 初值为 0.使用上述信号量后,三个进程不会同时使用输入设备,故不必再为输入设备设置互斥信号量。另外,还需要设置信号量 Sb,Sy,Sz 来表示数据 b 是否已经输入,以及 y,z 是否已经计算完成,他们的初值均为 0。
代码:
P1()
{
P(S1);
//从输入设备输入数据 a
V(S2);
P(Sb);
x=a+b;
P(Sy);
P(Sz);
//使用打印机打印出 x,y,z 的结果
}
P2()
{
P(S2);
//从输入设备输入数据 b
V(S3);
V(Sb);
y=a*b;
V(Sy);
V(Sy);
}
P3()
{
P(S3);
//从输入设备输入数据 c
P(Sy);
z=y+c-a;
V(Sz);
}
题 3:在读者写者问题中,允许多个读者同时读数据,但不允许写者与其他写者进程同时访问数据。另外要保证:一旦有写者等待,新到达的读者必须等待,知道该写者完成数据访问为止,用 PV 操作实现。
思路:这是一个“写优先”的读者-写者问题,在经典的“读优先”的读者-写者文章的 PV 操作中,只要再添加一个信号量 w=1,用以在写进程到达时封锁后续进程,即可实现“写优先”
代码:
int count=1;//记录当前读者数量
semaphore mutex=1;//保护更新 count 变量时的互斥
semaphore rw=1;//保证读者和写者互斥地访问文件
semaphore w=1;//实现“写优先”
writer()
{
while(1)
{
P(w);
P(rw);
//writing
V(rw);
V(w);
}
}
reader()
{
while(1)
{
P(w);
P(mutex);
if(count==0)
{
P(rw);
}
count++;
V(mutex);
V(w);
//reading
P(mutex);
count--;
if(count==0)
{
V(rw);
}
V(mutex);
}
}
题 4:有桥如图,车流方向如箭头所示,假设该桥上不允许两车交会,但允许同方向多个车一次通过(桥上可有多个同方向行驶的车),试用信号量 PV 实现
代码:
int countSN=0;//表示从南到北的汽车数量
int countNS=0;//表示从北到南的汽车数量
semaphore mutexSN=1;//保护 countSN
semaphore mutexNS=1;//保护 countNS
semaphore bridge=1;//互斥访问桥
StoN()
{
p(mutexSN);
if(countSN==0)
{
p(bridge);
}
countSN++;
v(mutexSN);
//过桥
p(mutexSN);
countSN--;
if(countSN==0)
{
v(bridge);
}
v(mutexSN);
}
NtoS()
{
p(mutexNS);
if(countNS==0)
{
p(bridge);
}
countNS++;
v(mutexNS);
//过桥
p(mutexNS);
countNS--;
if(countNS==0)
{
v(bridge);
}
v(mutexNS);
}