假设这个问题: 2个程序,A和B,1个进程,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-process将在其b阵列中具有a-array的副本。 这是一个信号量问题,解决方案可以是伪代码,因此语言无关紧要。
无效的初始解决方案: 我正在使用在0处初始化的信号量B,并且每次A写入某些内容时,我将B增加M,然后执行向下(A)。 在每个B循环开始时,我做了一个向下(B)。然后在B的每个循环结束时,我检查M读者是否已读取并存储var,如果有,我正在做(A)。
显然,上面允许单个B进程“消耗”应该通过M个阅读器传播的所有M个用法。 那么我如何 - 智能地 - 确保每个B只读取一次var?一组M个信号量,每个M一个,可以完成这项任务,但很可能不是这个练习所要求的。
答案 0 :(得分:1)
您可以使用四个信号量执行此操作。一个意思是“A读取均匀位置”。一个意思是“B写了一个偶数位置”。一个意思是“读一个奇怪的位置”。最后一个意思是“B写了一个奇怪的位置”。
A读取[0],然后发出第一个信号量M次信号,然后等待第二个信号量M次。 B写入b [0]然后发信号通知第二个信号量。
然后A读取[1],向第三个信号量发出M次信号,并在第四个信号量上等待M次。 B写b [1]并发信号通知第四个信号量。
然后在处理数组的奇数/偶数元素时在信号量之间切换。
很明显是一个家庭作业问题,因为这似乎不是一个现实的场景。
答案 1 :(得分:0)
实施例子
// 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++
}