1 writer, M readers to consume the same item

249 views Asked by At

Assume this problem: 2 programs, A and B, 1 process of A, M processes of M, 1 shared variable named 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; 
}

Now, what I need to do is make sure that for each loop in A, each of the M B-processes read the shared variable (once!) and store it in their arrays. So in the end each B-process will have a copy of the a-array in their b-arrays. This is a semaphore problem, and the solution can be in pseudocode, so language is irrelevant.

An initial solution which isn't working: I'm using a semaphore B initialized at 0, and each time A writes something, i'm increasing B by M, and doing a down(A). At the begining of each B loop I do a down(B). Then in the end of each loop of B, I check wether M readers have read and stored var, and if they have, I'm doing up(A).

Obviously the above lets a single B process "consume" all the M uses that were supposed to be spread through the M readers. So how do I - intelligently - make sure that each B will read each var only once? An array of M semaphores, one for each M, would do the job but it's most likely not what the exercise is asking for.

2

There are 2 answers

1
Nemo On BEST ANSWER

You can do this with four semaphores. One means "A read an even location". One means "B wrote an even location". One means "A read an odd location". The last means "B wrote an odd location".

A reads a[0], then signals the first semaphore M times, then waits on the second semaphore M times. B writes b[0] then signals the second semaphore once.

Then A reads a[1], signals the third semaphore M times, and waits on the fourth semaphore M times. B writes b[1] and signals the fourth semaphore once.

Then you toggle between the semaphores as you handle the odd/even elements of the array.

Pretty clearly a homework question, since this does not seem like a realistic scenario.

0
Déjà vu On

An exemple of implementation

// 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] )
}

a more complex algorithm could be made that use only [50] (and not [M][50) semaphores. Usually wait and release are presented by something similar to that (handled by the system), they run each in a critical section

wait ( sem ) {
   wait_in_sem_fifo_until (sem > 0) 
   sem--
}

release ( sem ) {
   sem++
}