1作者,M读者消费相同的项目

时间:2013-02-03 12:24:19

标签: algorithm synchronization shared-memory semaphore writers

假设这个问题: 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一个,可以完成这项任务,但很可能不是这个练习所要求的。

2 个答案:

答案 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++
}