某个计算会生成两个数组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
的正确实施?
(A)
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),因为在执行Y
中的关键部分之前,不应执行流程X
中的关键部分(a[i]
首先填充,必须用于b[i]
),因此在执行X
之后,根据Y
中关键部分条目中的选项(B),我们将找到{ {1}},R=1
,现在可以执行S=1
中的关键部分。
问题:正确答案是(C),我错在哪里?
答案 0 :(得分:2)
&#39; B&#39;如果它们不是二进制信号量将会工作:在这种情况下,X可以创建一个元素,增加一个信号量,Y可以等待该信号量并使用这些项目。信号量可以计算可用于处理的项目数。一个信号量就足够了。
但是你有二进制信号量。所以你只能算一个,例如X可以创建一个元素,用信号通知信号量,但是然后无法继续创建元素,因为它不能将该信号量值提升到&#34; 2&#34; (或者更多)。因此它必须等待Y识别该单个元素。并且等待引入第二个信号量,在当前元素被处理时发信号通知X.重要的是要记住,P等待信号量在必要时增加(并且V增加),因此X不能等待单个信号量返回到0,因为没有这样的操作。
这就是&#39; C&#39;正在做,S几乎是一个准备好的数据&#39;信号和R是'确认&#39;。 X说,它准备就绪,然后等待确认。当Y等待准备并发送确认时。
答案 1 :(得分:2)
首先,考虑为什么我们甚至需要两个信号量。原因是我们在这里有两件事要协调,
i
i
i+1
之前,X循环无法启动i
。所以有两个信号量,每个信号量管理上面的一个点。
信号量达到1需要从P
拨打ExitX
。 EntryY
需要致电V
。所以B已经离开这里了。要实现2,我们需要V
中的ExitX
和P
中的EntryY
。
所以看看A,没有人会增加任何东西,所以它是一个僵局。
C完成这项工作。
D不太正确,因为X
和Y
在调用该信号量的V
之前可能会两次P
。