[concurrency-interest] Is there something like an ordered or counting barrier

Oliver Zeigermann ozeigermann@apache.org
Wed, 29 Dec 2004 16:51:26 +0100


Hi David,

thanks a lot. This is exactly the kind of feedback I was hoping to get. :) 

Details inline...

On Wed, 29 Dec 2004 10:57:35 +1000, David Holmes <dholmes@dltech.com.au> wrote:
> Oliver,
> 
> > Because of that I made up a tiny class that does this for me
> >
> > http://cvs.apache.org/viewcvs.cgi/jakarta-commons/transaction/src/
> java/org/apache/commons/transaction/util/SequenceBarrier.java?view=markup
> >
> > and wanted to know if there are more elegant ways to do so and if this
> > makes sense in the first place.
> 
> The class as depicted is relatively simple - though I would not have called

Yes, it is simple. That's good, isn't it ;)

> the method "count". Basically you are providing a "barrier" that lets
> threads through in turn, where turn is indicated by the integer argument
> presented to the barrier. The timeout aspect is curious because you will
> proceed as if it were your turn on a timeout, even though it is not - that
> doesn't seem good.

Yes, right. Maybe throwing an exception would be better?!

> However, this barrier only controls the order in which threads pass the
> barrier, not the order in which they perform their actual tasks. For
> example, if a threads with arguments 1,2 and 3 are waiting when thread 0
> comes along, then all four threads could pass the barrier before any thread
> gets to do anything after the barrier. If the work itself were needed to be
> performed "in turn" then I would expect a different approach:
> 
>    waitForMyTurn();
>    doWork();
>    signalNextTurn();
> 
> So while the class does something, I'm not sure it does what you actually
> want it to do.

Very good observation! My solution looks like

count(0);
doWork();
count(1);

count(4);
doWork();
count(5);

and another thread may look like

count(2);
doWork();
count(3);

But

waitForTurn(0);
doWork();
signalNextTurn(0);

would indeed be better.

Sometimes stuff is even more complicated. Consider you want to signal
the next turn, but are blocked by a lock before doing so. The thread
that will release your block however needs your next signal to
proceede. My solution looks like

waitForTurn(0);
synchronized (lock) {
  signalNextTurn(0);
  lock.acquireSomething();  
}

and the other thread may look like

waitForTurn(1);
synchronized (lock) {
  signalNextTurn(1);
  lock.releaseSomething();  
}

I thought all this was a very common problem. How are others dealing
with it? Is this an absurd approach?

Oliver