CountDownLatch
is a signalling mechanism that allows one or more threads to wait until a set of operations being performed in other threads completes.
A CountDownLatch
is initialized with a given count (the number of operations after which the waiting threads will wake up).
The await method blocks until the count of operations reaches zero. As each thread complete its assigned task, it calls countDown()
to decrement the count.
For example, below we create a CountDownLatch
of count 2, we start two threads which call await on it. Next, we call countDown()
couple of times. Finally, we wait till the two threads are done awaiting.
public void testCountDownLatch() { final CountDownLatch latch = new CountDownLatch(2); final boolean done[] = new boolean[2]; Thread t1 = new Thread(new Runnable(){ public void run() { try { latch.await(); done[0] = true; } catch (InterruptedException e) { fail(e.toString()); } } }); t1.start(); Thread t2 = new Thread(new Runnable(){ public void run() { try { latch.await(); done[1] = true; } catch (InterruptedException e) { fail(e.toString()); } } }); t2.start(); try { Thread.sleep(100); } catch (InterruptedException e) { fail(e.toString()); } latch.countDown(); latch.countDown(); try { t1.join(); } catch (InterruptedException e) { fail(e.toString()); } try { t2.join(); } catch (InterruptedException e) { fail(e.toString()); } assertTrue(done[0] && done[1]); }
Class Diagram
CountDownLatch
internally depends on the AbstractQueuedSynchronizer . Both await
and countDown()
methods delegate the call to the abstract class.
Await
await()
delegates the call to AbstractQueuedSynchronizer
. CountDownLatch
implements the tryAcquireShared()
method. If the count is 0 (internal state), it considers the latch as already released else will queue up the thread and will block the thread.
In the below diagram, we create a CountDownLatch
for count 2. Next, we create two threads that wait for the release of latch. Initially when a thread calls await, it simply waits in a queue as the count is still != 0
Release
countDown()
delegates the call to AbstractQueuedSynchronizer
. CountDownLatch
implements the tryReleaseShared()
method. If the count is already 0 (internal state), it simply returns else decrements the count. If after decrementing, the count becomes zero then it will signal for the release of all the waiting threads.
In the below diagram, we call countDown()
couple of times to release the latch. Whenever we call countDown()
, the count decrements. Once it becomes equals to 0, the latch gets released and unparks the successor thread which in turn propagates the release to all the waiting threads.