出现在两个进程中。
(2) 确定互斥或同步的规则
在F1(X)+F2 (X)中,必须在F1(X)和F2(X)计算完毕,才能进行加法运算,因此本问题是同步问题。
(3) 同步的操作流程 〈进程main〉
创立进程p1来计算F1(X); 创立进程p2来计算F2(X);
F1(X)计算是否完成?没有,等待;① F2(X)计算是否完成?没有,等待;② 进行加法运算。
〈进程p1〉
y1= F1(X);
设置F1(X)计算完成标志; ③
〈进程p2〉 y1= F2(X);
设置F2(X)计算完成标志。 ④
(4) 确定信号量的个数和含义
根据同步规则以及操作流程确定信号量的个数是2个,S1和S2: S1含义是F1(X)计算是否完成; S2含义是F2(X)计算是否完成。 (5) 确定信号量的初值 S1=0; S2=0。
(6) 确定P、V操作的位置
上面①处是一个P操作,P(S1); 上面②处是一个P操作,P(S2); 上面③处是一个V操作,V(S1); 上面④处是一个V操作,V(S2)。 解法1 Main ( )
Public y, y1, y2,. P1, P2 Semaphore S1,S2 {
S1=0; S2=0;
P1=Creat(N-F1, F1,x,……); P2=Creat(N-F2, F2, x,……); P(S1); P(S2); y=y1+y2;
}
Procedure F1(x) {
y1= 计算1; V(S1); }
Procedure F2(x) {
y2=计算2; V(S2)
}
解法2 Main ( )
Public y, y1, y2,. P1,x Semaphore S1 { input(x); S1=0;
P1=Creat(N-F1, F1,x,……); Y2=F2(x); P(S1); y=y1+y2; }
Procedure F1(x) {
y1= 计算1; V(S1) }
采用2个进程和1个信号量来实现Y=F1(X)+F2 (X)的时候,采用的方法是父进程创立子进程,F1(X)在子进程中计算,F2 (X)在父进程中计算,因此F1(X)和F2(X)计算仍然是并发进行的。S1信号量的含义为F1(X)是否完成。改进的方法比原来的方法节约一个进程和一个信号量,但并发操作的程度并没有降低。
进程同步6:
例3.2.10 如下图所示,有多个PUT操作同时向BUFF1放数据,有一个MOVE操作不断地将BUFF1的数据移到Buff2,有多个GET操作不断地从Buff2中将数据取走。BUFF1的容量为m,BUFF2的容量是n, PUT、 MOVE、 GET每次操作一个数据,在操作的过程中要保证数据不丢失。试用P、V原语协调PUT、 MOVE的操作,并说明每个信号量的含义和初值。
PUT GET MOVE Buff1 Buff2
图 4.2 进程操作图
解
(1) 确定并发的操作
本问题是把2个消费者和生产者问题综合在一起。多个PUT操作与一个MOVE操作并发进行,多个GET操作与一个MOVE操作并发进行。因此本题涉及三类进程:PUT类进程,有多个;GET类进程,有多个;MOVE类进程,有1个。
(2) 操作规则
1) 只有buff1有空间才能进行PUT操作;
2) 只有buff1有数据,buff2有空间才能进行MOVE操作; 3) 只有buff2有数据才能进行GET操作; 4) 不允许多个进程同时操作buff1; 5) 不允许多个进程同时操作buff2。
(3) 操作流程
repeat
判断buff1是否有空间,没有则等待; 是否可操作buff1;
PUT;
设置buff1可操作标志; 设置buff1有数据的标志; until false }
repeat
判断buff1是否有数据,没有则等待;
判断buff2是否有空间,没有则等待; 是否可操作buff1; 是否可操作buff2;
MOVE;
设置buff1可操作标志; 设置buff2可操作标志;
设置buff1有空间标志; 设置buff2有数据标志; until false }
{
repeat
判断buff2是否有数据,没有则等待; 是否可操作buff2; GET;
设置buff1可操作标志; 设置buff1有空间标志; until false
}
(4) 信号量
设置6个信号量full1、empty1、B-M1、full2、empty2、B-M2,它们的含义和初值如下:
1) full1表示buff1是否有数据,初值为0; 2) empty1表示buff1有空间,初值为m; 3) B-M1表示buff1是否可操作,初值为1; 4) Full2表示buff2是否有数据,初值为0; 5) Empty2表示buff2有空间,初值为n; 6) B-M2表示buff2是否可操作,初值为1; (5) P、V操作实现
{
repeat
P(empty1); /*判断buff1是否有空间,没有则等待 */ P(B-M1); /*是否可操作buff1*/ PUT;
V(B-M1); /*设置buff1可操作标志 */ V(full1); /*设置buff1有数据的标志 */ until false }
repeat
P(full1); /*判断buff1是否有数据,没有则等待*/
P(empty2); /*判断buff2是否有空间,没有则等待*/ P(B-M1); /*是否可操作buff1 */ P(B-M2); /*是否可操作buff2 */ MOVE;
V(B-M1); /*设置buff1可操作标志*/ V(B-M2); /*设置buff2可操作标志*/
V(empty1); /*设置buff1有空间标志*/ V(full2); /*设置buff2有数据标志*/ until false }
{
repeat
P(empty2); /*判断buff2是否有空间,没有则等待 */ P(B-M2); /*是否可操作buff2*/ GET;
V(B-M2); /*设置buff2可操作标志 */ V(full2); /*设置buff2有数据的标志 */ until false
}
进程同步7:
一售票厅只能容纳300人,当少于300人时,可以进入;否则,需在外等候。若将每一个购票者作为一个进程,请用P、V操作编程,并写出信号量的初值。
解 〈购票者进程〉 { ┋ P(S);
进入售票厅; 购票;
退出售票厅; V(S); }
信号量的初值 S=300
进程同步8:
针对如下所示的优先图解答下列问题: S1
S4 S2 S3
S5
S6
图 4.4 进程优先图
(1)仅使用并发语句能否将其转换成正确的程序?如果能则写出相应程序,如果不能则说明为什么?
(2)若可以使用信号量机构,该优先图将如何转换成正确的程序? 解
(1) 如果仅用并发语句不能将其转换成程序。 S3 S5 S2 S5 S2 S4 S1S4