Breaking a thread coordinating cyclic barrier

Breaking a thread coordinating cyclic barrier

A CyclicBarrier is a synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. Suppose that in a test, there is a Runnable which needs to be executed by multilpe threads at the same time for multiple rounds. Then the beginning and ending for each round can be coordinated by a CyclicBarrier that a manager thread can signal the beginning of a round to all the worker threads, and wait until all the worker threads finish to end the round. The beginning and ending can then happen for more rounds.

Basically, the manager thread and all the worker threads need to call CyclicBarrier.await() for both the beginning and the ending of a round. Problems could happen if a worker thread encounters a RuntimeException during a round and the RuntimeException is not caught. The worker thread will not reach the ending of the round and other worker threads and the manager thread will be waiting forever. The question arises here is how can a worker thread let other threads know when the worker thread encounters a RuntimeException. This post discusses a solution using the CyclicBarrier itself which is already coordinating all the threads.

CyclicBarriers use an all-or-none breakage model for failed synchronization attempts: If a thread leaves a barrier point prematurely, all other threads waiting at that barrier point will also leave abnormally and receive either a BrokenBarrierException or an InterruptedException. This behavior implies that if somehow we can break the CyclicBarrier in question after a RuntimeException is caught, other threads will know even if the RuntimeException is re-thrown.

To break a CyclicBarrier, what we can do is "leave a barrier point prematurely". For the worker thread encountering a RuntimeException, the worker thread is not at the barrier point yet. To make it get to a barrier point and also leave prematurely, we let it call CyclicBarrier.await() with the interrupted status set to true. The interrupted status is set by the worker thread itself via interrupting itself. To avoid side effects, we also save and restore the existing interrupted status before and after breaking the CyclicBarrier, respectively.

  1. public class CyclicBarrierUtility {
  3.   public static void breakCyclicBarrier(final CyclicBarrier barrier) {
  4.     if(Thread.currentThread().isInterrupted()) {
  5.       try {
  6.         barrier.await();
  7.       } catch(final BrokenBarrierException unused) {
  8.         Thread.currentThread().interrupt();
  9.       } catch(final InterruptedException unused) {
  10.         Thread.currentThread().interrupt();
  11.       }
  12.     } else {
  13.       Thread.currentThread().interrupt();
  14.       try {
  15.         barrier.await();
  16.       } catch(final BrokenBarrierException unused) {
  17.         Thread.interrupted();
  18.       } catch(final InterruptedException unused) {
  19.         Thread.interrupted();
  20.       }
  21.     }
  22.   }
  23. }

If no RuntimeException is encountered, the manager thread can still choose to break the CyclicBarrier to signal the ending of all rounds to the worker threads. This choice makes breaking the CyclicBarrier the consistent exit point for both normal and abnormal scenarios.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.

More information about formatting options

To prevent automated spam submissions leave this field empty.