Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.programming > #4127

Re: randezvous with semaphore have a deadlock

From Kaz Kylheku <kaz@kylheku.com>
Newsgroups comp.programming
Subject Re: randezvous with semaphore have a deadlock
Date 2014-03-04 08:35 +0000
Organization Aioe.org NNTP Server
Message-ID <20140303232823.685@kylheku.com> (permalink)
References <365a702c-a9ed-41a4-9560-d689c72f990f@googlegroups.com>

Show all headers | View raw


On 2014-03-03, bertanimauro@gmail.com <bertanimauro@gmail.com> wrote:
> Hi, I have a problem with an implementation of a randezvous with the
> semaphore structures.

There is a problem implementing almost anything with semaphores.

Semaphores are the "goto" of process synchronization.

Which is why it is so amusing that they were proposed by Dijkstra, the
staunch proponent of proving programs correct and opponent of goto.

> What I want to do is: The synchronization requirement is that no thread
> executes critical point until after all threads have executed rendezvous. You
> can assume that there are n threads and that this value is stored in a
> variable, n, that is accessible from all threads. When the first n − 1 threads
> arrive they should block until the nth thread arrives, at which point all the
> threads may proceed.

This is also called a "barrier": a synchronization primitive which waits for N
threads to call a single function, "wait".

A useful further refinement in the barrier (an essential feature, I would say)
is that one of these threads returns from the barrier with a special return
value which tells it it is the "serial thread".  The serial thread can then
perform some action that only one thread should do.

For instance N threads can "map" some data in parallel in one processing
phase, rendezvous at the barrier, and then the serial
thread can "reduce" the the outputs of the prior parallel computations.

> I try this soltion:
> multiplex = new Semaphore(4) //n = 4
> mutex = new Semaphore(1)
>
> multiplex.wait()
> mutex.wait()
> criticalSection()
> mutex.signal()
> multiplex.signal()
> I have instantiace 10 threads and the program reaches deadlock
> before three threads remains in the multiplex

Although this is not a correct approach to implementing barriers, the threads
should be able to pass through this flow without deadlock. Every wait is
balanced by a signal.

Possibly, you might be using some poorly designed semaphore type which
saturates at (does not increment past) a maximum value, thereby 
causing lost wakeups.

You should show your actual source code with the real types that you're using.

The solution you have cannot work because it doesn't exhibit the behavior of
blocking n - 1 threads, and then releasing the whole herd when thread n
arrives.  Semaphores do not do this "out of the box"; you have to
orchestrate the semaphores into a clever "mouse trap".

One idea is to implement the barrier with a "barrier manager" thread.  The
barrier wait operation posts a request to the manager's receive queue and
blocks, waiting for a reply. The manager monitors the queue, and counts the
requests.  When it collects ten requests, then it replies to all of the
messages.

Here is a simpler idea:

  n_waiting = 0
  mutex = Semaphore(0)
  barrier = Semaphore(0)

  wait_op:
    mutex.wait()               // acquire lock
    if (++n_waiting == n)      // am I thread n?  
      n_waiting = 0
      repeat n-1               // yes: wake the other n-1
          barrier.signal()
      mutex.signal()           // give up lock
      return true              // report: "I am the serial thread"
    else                       // I am not thread #n
      mutex.signal()           // give up lock   
      barrier.wait()           // wait for thread #n to signal me
      return false             // report: "I am not the serial thread"

We keep the lock over the barrier.signal() operation, because as soon as we
kick the barrier semaphore, the threads will want to spin around and call
wait_op again. That will interfere with the count.

We can actually allow them to do that, by doing it like this.
This should still work:

  n_waiting = 0
  mutex = Semaphore(0)
  barrier = Semaphore(0)

  wait_op:
    I_am_serial = false

    mutex.wait()
    if (n_waiting == n - 1)
      n_waiting = 0
      i_am_serial = true
    else
      n_waiting++
    mutex.signal()

    if (I_am_serial)
      repeat n - 1   
        barrier.signal()
    else
      barrier.wait()

    return I_am_serial

Back to comp.programming | Previous | Next — Previous in thread | Find similar | Unroll thread


Thread

randezvous with semaphore have a deadlock bertanimauro@gmail.com - 2014-03-03 07:07 -0800
  Re: randezvous with semaphore have a deadlock Kaz Kylheku <kaz@kylheku.com> - 2014-03-04 08:35 +0000

csiph-web