3

假设这个问题:2个程序,A和B,A的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 进程都会在它们的 b 数组中拥有一个 a 数组的副本。这是一个信号量问题,解决方案可以是伪代码,因此语言无关紧要。

一个不起作用的初始解决方案:我正在使用初始化为 0 的信号量 B,每次 A 写一些东西时,我都会将 B 增加 M,然后执行 down(A)。在每个 B 循环开始时,我都会执行 down(B)。然后在 B 的每个循环结束时,我检查 M 阅读器是否读取并存储了 var,如果有,我正在做 up(A)。

显然,以上内容让单个 B 进程“消耗”了所有应该通过 M 个阅读器传播的 M 个用途。那么我如何 - 智能地 - 确保每个 B 只会读取每个 var 一次?一组 M 信号量,每个 M 一个,可以完成这项工作,但这很可能不是练习所要求的。

4

2 回答 2

1

你可以用四个信号量来做到这一点。一个意思是“A读取一个偶数位置”。一个意思是“B写了一个偶数位置”。一个意思是“A读取一个奇怪的位置”。最后一个意思是“B写了一个奇怪的位置”。

A 读取 a[0],然后向第一个信号量发出 M 次信号,然后在第二个信号量上等待 M 次。B 写入 b[0] 然后向第二个信号量发出一次信号。

然后 A 读取 a[1],向第三个信号量发出 M 次信号,并在第四个信号量上等待 M 次。B 写入 b[1] 并向第四个信号量发出一次信号。

然后在处理数组的奇数/偶数元素时在信号量之间切换。

很明显这是一个家庭作业问题,因为这似乎不是一个现实的场景。

于 2013-02-03T15:19:36.473 回答
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++
}
于 2013-02-03T15:07:19.343 回答