Abstract: CountDownLatch is easy to understand, but can be hard to use, especially the await() method that throws InterruptedException. In this newsletter we show how we can create our own synchronizer based on the AbstractQueuedSynchronizer.
Welcome to the 292nd edition of The Java(tm) Specialists' Newsletter, sent to you from, yes you guessed it, the stunning Island of Crete. Greece took the painful path of a strict lockdown from November until May, together with making it easy to get vaccinated for those who wanted to. The hope was that tourists would come flocking to Greece during the summer months, bringing much needed economic relief. It seems to have paid off. 2021 was not nearly as good as 2019, but there are a lot of tourists here, enjoying the beaches, fine food, good weather. We even have a miniature version of JCrete this year, consisting of 100% Java Champions, all vaccinated of course.
javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.
A few months ago, I started recording detailed walkthroughs of how the concurrency utilities work in Java. So far I have created a course about the ArrayBlockingQueue and the CopyOnWriteArrayList/Set.
   The next course that I want to create is about the
   AbstractQueuedSynchronizer. I had known about the class for
   a very long time and I knew that it was at the cornerstone
   of many concurrency classes. However, I had never investigated
   how it truly worked, until now. Recently I was looking at
   a new open source project that provides a parser for log
   files and they were using the CountDownLatch in a rather
   awkward fashion:
   
private final CountDownLatch deployed = new CountDownLatch(1);
public void awaitDeployment() {
  try {
    deployed.await();
  } catch (InterruptedException e) {
    LOGGER.throwing("JVMEventSource", "awaitDeployment", e);
  }
}
public void start() {
  deployed.countDown();
}
   I shudder when I see InterruptedException handled like this.
   Interruptions are orthogonal to the code and we never know
   when a thread might be interrupted, nor which other thread
   has issued the interrupt. We also do not know who might want
   to know later whether our thread was interrupted. Before
   throwing the InterruptedException, the interrupt status on
   the current thread is cleared. Thus we would lose that status
   on the thread if we catch the InterruptedException. On the
   other hand, we also do not want to propagate the exception
   from the method, otherwise the caller will have to deal with
   it. Most likely we actually want to block the caller until
   we are completely deployed and ready for action. When I saw
   that code, I immediately refactored it into an
   uninterruptible wait, like so:
   
private final CountDownLatch deployed = new CountDownLatch(1);
public void awaitDeployment() {
  boolean interrupted = Thread.interrupted();
  while(true) {
    try {
      deployed.await();
      if (interrupted) Thread.currentThread().interrupt();
      break;
    } catch (InterruptedException e) {
      interrupted = true;
    }
  }
}
public void start() {
  deployed.countDown();
}
   After inspecting the rest of the project, I found 3 other
   places that were coded in a similar fashion. In all cases
   the CountDownLatch had size one and these were used as a way
   to indicate whether the service had been started up. A
   starting gun, if you will. Even though the code above will
   work, it does have the disadvantage that every time the
   thread is interrupted, a new InterruptedException would be
   constructed. Exceptions are particularly expensive to create
   because of the stack trace. It is typically best to avoid
   that cost.
   
   Fortunately I had already done some research for my new
   mini-course on the AbstractQueuedSynchronizer and thus knew
   that it would be trivial to make a new synchronizer, similar
   to the CountDownLatch, but which would do precisely what we
   were looking for. Since the CountDownLatch is in the public
   domain, we are allowed to copy and paste the code to our
   heart's content. I did that to get the initial structure
   and then did some refactoring to simplify it a bit. One thing
   to note is that some of the parameters are not used in this
   synchronizer. I thus name them "unused" so as to avoid
   confusion.
   
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
 * A StartingGun for services, where we can wait for one
 * particular service to start up.
 *
 * Instead of {@link java.util.concurrent.CountDownLatch}, we
 * have a custom concurrency utility called StartingGun, which is
 * like a CountDownLatch with a count of 1 and where the
 * awaitUninterruptibly() method does not throw an exception.
 * Similarly to the CountDownLatch, this uses the {@link
 * AbstractQueuedSynchronizer} for the synchronization.
 *
 * @author Dr Heinz M. Kabutz
 */
public class StartingGun {
  private static final int UNUSED = 0;
  /**
   * Synchronization control For StartingGun.
   * Uses AQS state to represent whether we are ready.
   */
  private final AbstractQueuedSynchronizer sync =
      new AbstractQueuedSynchronizer() {
        private static final int SUCCESS = 1;
        private static final int FAILURE = -1;
        private static final int READY = 1;
        protected int tryAcquireShared(int unused) {
          return (getState() == READY) ? SUCCESS : FAILURE;
        }
        protected boolean tryReleaseShared(int unused) {
          setState(READY);
          return true;
        }
      };
  /**
   * Wait for the starting gun to fire, without propagating the
   * InterruptedException.
   */
  public void awaitUninterruptibly() {
    sync.acquireShared(UNUSED);
  }
  /**
   * Indicate that the service is ready for operation.
   */
  public void ready() {
    sync.releaseShared(UNUSED);
  }
}
   My StartingGun has a few minor differences with the
   CountDownLatch. First off, we call sync.acquireShared(),
   whereas the CountDownLatch calls
   sync.acquireSharedInterruptibly(). This means that interrupts
   are saved until we are done with waiting for the state,
   without causing unnecessary exceptions.
   Also, since this is meant to be used with a single service,
   we don't need a count. It is more like a single boolean latch
   that is either open or closed.
   
Here is an example of how I used it to simplify the code:
private final StartingGun deployed = new StartingGun();
public void awaitDeployment() {
    deployed.awaitUninterruptibly();
}
public void start() {
    deployed.ready();
}
Nice and easy!
Kind regards
Heinz
We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)
We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.