>假设这个问题:2 个程序,A 和 B,1 个 A 进程,M 进程 M,1 个名为 var 的共享变量
A
main(){
int i, a[50];
for(i=0;i<50;i++)
var = a[i];
}
B
main(){
int i, b[50];
for(i=0;i<50;i++)
b[i] = var;
}
现在,我需要做的是确保对于 A 中的每个循环,每个 M B 进程都读取共享变量(一次!)并将其存储在它们的数组中。因此,最终每个 B 进程的 b 数组中都会有一个 a 数组的副本。这是一个信号量问题,解决方案可以用伪代码,所以语言是无关紧要的。
一个不起作用的初始解决方案:我使用的是在 0 处初始化的信号量 B,每次 A 写入一些东西时,我都会将 B 增加 M,并执行 down(A)。在每个 B 循环的开头,我做一个 down(B)。然后在 B 的每个循环结束时,我检查 M 阅读器是否读取并存储了 var,如果有,我正在做 up(A)。
显然,上述内容允许单个 B 进程"消耗"所有应该通过 M 阅读器传播的 M 用途。那么我如何 - 智能地 - 确保每个 B 只会读取每个 var 一次?一个 M 信号量数组,每个 M 一个,可以完成这项工作,但这很可能不是练习所要求的。
您可以使用四个信号量来执行此操作。 一个意思是"读取均匀位置"。一个意思是"B写了一个均匀的位置"。 一个意思是"读一个奇怪的位置"。 最后一个意思是"B写了一个奇怪的位置"。
A 读取 a[0],然后向第一个信号灯发出 M 次信号,然后等待第二个信号量 M 次。 B 写入 b[0],然后向第二个信号灯发出一次信号。
然后 A 读取 a[1],向第三个信号量 M 次发出信号,并等待第四个信号量 M 次。 B 写入 b[1] 并向第四个信号灯发出一次信号。
然后,在处理数组的奇数/偶数元素时在信号量之间切换。
很明显,这是一个家庭作业问题,因为这似乎不是一个现实的情况。
实现示例
// Before A and any B run, init 2 x M x 50 semaphores
// (set to 0, but usually they're automatically initialized by the system to
// something equivalent to 0, meaning no-access)
// Create [M][50] semaphores and init to no access for Bs
for (i=0 ; i<M ; i++)
for (j=0 ; j<50 ; j++)
asems[i][j] = 0; // no access for Bi index j
// Create [M][50] semaphores to block A before it goes to next iteration
for (i=0 ; i<M ; i++)
for (j=0 ; j<50 ; j++)
bsems[i][j] = 0; // no access for A until all B's say ok for that index
// A
for (i=0 ; i<50 ; i++) {
var = a[i];
// release a-sems and, then, wait for b-sems in two separate loops
// or you may have a deadlock if you use one loop only...
// (since we don't know if B[i] always ends before B[i+1])
for (j=0 ; j<M ; j++) {
release ( asems[j][i] )
}
for (j=0 ; j<M ; j++) {
wait ( bsems[j][i] )
}
}
// a B
ME = id // id is the B's unique id from 0 to 49
for (i=0 ; i<50 ; i++) {
wait ( asems[ME][i] )
b[i] = var
relase ( bsems[ME][i] )
}
可以制作一个更复杂的算法,仅使用[50](而不是[M][50)信号量。通常等待和发布由类似于(由系统处理)的东西呈现,它们在关键部分中运行每个
wait ( sem ) {
wait_in_sem_fifo_until (sem > 0)
sem--
}
release ( sem ) {
sem++
}