2

I got a bunch of threads that perform calculations. They are "synchronized" using a CyclicBarrier. When any thread's run() method finishes, I want all other threads to exit as well once they call await() on the barrier the next time.

So far, everything I've tried either hangs at the await() calls or results in a broken barrier. Any tips?

EDIT: Here's the (basic) code:

public MyClass implements Runnable {
    public void run() {
        while (true) {
            if (someCondition) {
                // quit other threads when they call await()
                return;
            }
            barrier.await();
    }
}
ryyst
  • 9,563
  • 18
  • 70
  • 97

2 Answers2

3

reset() will awaken all waiting threads with a thrown exception

you can then use the await as so

private static volatile boolean shouldStop=false;

public void run() {
    try{
        while (true) {
            if (someCondition) {
                // quit other threads when they call await()
                return;
            }
            try{
                if(shouldStop)return;
                barrier.await();
            }catch(BrokenBarrierException e){
                //someone stopped 
                return;
            }
       }
   }finally{
       shouldStop =true;
       barrier.reset();
   }
}

you can also call a method for the if(shouldStop) check

ratchet freak
  • 47,288
  • 5
  • 68
  • 106
  • What if the barrier breaks for some other reasons? Your solution is actually like I have this implemented currently, but I'm not happy with it. – ryyst Jun 28 '11 at 21:27
  • @ryyst, What are you not happy about? Without knowing this it is hard to suggest an alternative. – Peter Lawrey Jun 28 '11 at 21:31
  • do an extra check in the catch but if the barrier is broken there needs to be some extra syncs before you can continue and breakage happens only when you use timeouts and interrupts (or a barrier action throwing an exception) – ratchet freak Jun 28 '11 at 21:34
0

From the sounds of it you probably want a CountDownLatch. Assuming you know the number of threads/participants, you simply create one for that many and then when your thread is done count down and await the latch:

final int workers = …
final CountDownLatch latch = new CountDownLatch(workers);

void doSomething() throws InterruptedException {
  …
  latch.countDown();
  latch.await(); // blocks, throws InterruptedException
}

Compared to CyclicBarrier, CountDownLatch is not reusable, you only use it once. It does however separate the waiting and the releasing concerns, so you can for instance have another thread that allows the threads through.

All that said, if you do need a CyclicBarrier a slight variation on the above code should work:

final int workers = …
final CyclicBarrier barrier = new CyclicBarrier(workers);

void doSomething() throws InterruptedException, BrokenBarrierException {
  …
  latch.await(); // blocks, throws InterruptedException, BrokenBarrierException
}

however, if any thread is interrupted or barrier.reset() is called then barrier is broken and the exception is thrown.

Jed Wesley-Smith
  • 4,686
  • 18
  • 20