某个计算会生成两个数组 a
和 b
a[i]=f(i) for 0 ≤ i < n and b[i] = g(a[i]) for 0 ≤ i < n
. 假设此计算被分解为两个并发进程 X
和 Y
,以便 X
计算数组 a
和 Y
计算数组 b
. 这些进程使用两个二进制信号量 R
和 S
,两者都初始化为零 . 数组 a
由两个进程共享 . 这些过程的结构如下所示 .
Process X:
private i;
for (i=0; i < n; i++) {
a[i] = f(i);
ExitX(R, S);
}
Process Y:
private i;
for (i=0; i < n; i++) {
EntryY(R, S);
b[i]=g(a[i]);
}
以下哪一项代表 ExitX
和 EntryY
的CORRECT实现?
(一个)
ExitX(R, S) {
P(R);
V(S);
}
EntryY (R, S) {
P(S);
V(R);
}
(B)
ExitX(R, S) {
V(R);
V(S);
}
EntryY(R, S) {
P(R);
P(S);
}
(C)
ExitX(R, S) {
P(S);
V(R);
}
EntryY(R, S) {
V(S);
P(R);
}
(d)
ExitX(R, S) {
V(R);
P(S);
}
EntryY(R, S) {
V(S);
P(R);
}
我相信答案应该是(B)因为在 X
中的临界区执行之前不应该执行进程 Y
中的临界区(首先填充 a[i]
,这必须用于 b[i]
),所以在 X
执行之后再根据选项(B)在 Y
的临界区条目中我们会找到 R=1
,_ S=1
,所以现在可以执行 Y
中的临界区 .
Question :正确答案是(C),我错在哪里?
2 回答
如果它们不是二进制信号量,'B'将起作用:在这种情况下,X可以创建一个元素,增加一个信号量,Y可以等待该信号量并使用这些项 . 信号量可以计算可用于处理的项目数 . 一个信号量就足够了 .
但是你有二进制信号量 . 所以你只能算一个,例如X可以创建一个元素,发信号通知信号量,但是然后in不能继续创建元素,因为它不能将该信号量值提高到“2”(或更多) . 因此它必须等待Y识别该单个元素 . 并且等待引入第二个信号量,在当前元素被处理时发信号通知X.重要的是要记住,P等待信号量在必要时增加(并且V增加),因此X不能等待单个信号量返回到0,因为没有这样的操作 .
这就是'C'正在做的事情,S实际上是'数据就绪'信号而R是'确认' . X说,它准备就绪,然后等待确认 . Y等待准备好并发送确认 .
首先,考虑为什么我们甚至需要两个信号量 . 原因是我们在这里有两件事要协调,
在X循环结束之前
i
i
在Y完成
i
之前i+1
.所以有两个信号量,每个信号量管理上面的一个点 .
信号量达到1将需要从
ExitX
调用P
. 并且EntryY
需要调用V
. 所以B已经离开这里了 . 为了达到2,我们需要ExitX
中的V
和EntryY
中的P
.所以看看A,没有人会增加任何东西,所以这是一个僵局 .
C完成这项工作 .
D不是很正确,因为
X
和Y
可能会在调用该信号量的任何_2390181之前两次命中V
.