CountdownLatch
CountdownLatch is a simple yet useful utility which allows one or more threads to wait until a set of operations has been completed.
When we create an instance of CountDownLatch, as part of the constructor arguments, we specify the number of threads it should wait for; all such threads are required to count down by invoking countDown() on the latch object once they are completed or ready to do the job. As soon as the count reaches zero, the waiting task starts running. Note that to wait, a thread has to explicitly invoke await() or its time-out version on the latch object — invoking countDown() doesn’t automatically cause a thread to wait. This provides us with an interesting flexibility — the threads calling countDown() need not necessarily be the same as the threads waiting. This flexibility makes it easier to solve a lot of problems with CountdownLatch as opposed to other synchronization aiding classes
A CountDownLatch is initialised with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon — the count cannot be reset.
To initialise a CountDownLatch, we can use this constructor and provide the count as a constructor argument
public CountDownLatch(int count)To trigger a countdown, the following method needs to be invoked:
public void countDown()The call to countDown() decrements the latch count, releasing all waiting threads if the count reaches zero. If the current count is greater than zero, then it is decremented. If the new count is zero, then all waiting threads are re-enabled for thread scheduling. If the current count is already zero, then nothing happens.
To wait on a latch, a thread needs to invoke either of the following methods :
public void await() throws InterruptedException
public boolean await(long timeout, TimeUnit unit) throws InterruptedExceptionCauses the current thread to wait until the latch has counted down to zero, unless the thread is interrupted, or the specified waiting time elapses. If the current count is zero, then this method returns immediately with the value true.
Get Kaustubh Saha’s stories in your inbox
Join Medium for free to get updates from this writer.
Note that for the timeout version of await, the return type is boolean and not void. It returns true if the count reaches zero and false if the waiting time elapses before the count reaches zero.
It’s generally safer to use the timeout version of the await method instead of the no-args version, as in the absence of a timeout, in case the worker thread runs into an Exception before calling countDown(), we might have a situation where count never reaches zero.
In order to illustrate how to use a countdown latch, let's consider the following Java code that simulates a deadlock:
class Dummy {
synchronized void m1 (Dummy other) {
System.out.println(Thread.currentThread().getName()+ " : Executing m1");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
other.m2();
}
synchronized void m2() {
System.out.println(Thread.currentThread().getName()+ " : Executing m2");
}
}
class DeadlockDemo implements Runnable {
Dummy a;
Dummy b;
public DeadlockDemo(Dummy a, Dummy b) {
this.a = a;
this.b = b;
}
@Override
public void run() {
a.m1(b);
}
}and the main method:
public static void main(String[] args) {
Dummy a = new Dummy();
Dummy b = new Dummy();
Runnable r1 = new DeadlockDemo(a, b);
Runnable r2 = new DeadlockDemo(b, a);
new Thread(r1).start();
new Thread(r2).start();
}The reason we used a sleep() in method m1 was to ensure that the first thread doesn’t acquire both the locks even before the second thread has acquired a single lock.
Now we can rewrite the class Dummy using CountDownLatch as :
class Dummy {
static CountDownLatch latch = new CountDownLatch(2);
synchronized void m1 (Dummy other) {
System.out.println(Thread.currentThread().getName()+ " : Executing m1");
try {
latch.countDown();
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
other.m2();
}
synchronized void m2() {
System.out.println(Thread.currentThread().getName()+ " : Executing m2");
}
}So we have created a latch with count 2, and each thread calls countDown() and await(), before invoking m2(). As a result, thread 1 can't proceed with m2() until thread 2 has invoked countDown() on the latch. So, we’ll still have a deadlock, but won't need a sleep (or some other form of delay)
The rest of the code remains the same








