Countdown Latch
Countdown Latch is one of the other synchronizing mechanism that’s made available in Java. Although it may appear to be very similar to Cyclic Barrier.Countdown Latch works very similar to a multi-lever latch lock. Access through the lock is possible only when all the levers are exercised (count down)
Java Countdown latch also works on the same principle, one or more threads can be made to wait on the latch using the await() method. This latch is made open only when all the count downs are performed on the latch. The number of count downs requires to open the latch is specified during the initialization of the Countdown Latch.
Few notable differences with Cyclic Barrier.
- A single thread can perform all the count downs if required as it performs various operations.
- In case of Cyclic barrier, distinct threads have to arrive and wait at the barrier for it be crossed.
- Threads performing the countdown do not wait at the latch after the count down.
CountDownLatch latch = new CountDownLatch(2);
We, will create a simple program that would perform addition of two matrices (2*2). To achieve parallelism, each row of the matrix is worked on by a seperate thread.class Matrix {
CountDownLatch latch;
ExecutorService executorService;
int[][] result;
Matrix() {
this.latch = new CountDownLatch(2);
executorService = Executors.newFixedThreadPool(2);
}
}
Here, latch has been initialized with value two
executor service created with fixed Thread Pool for two threads
int[][] add(int[][] matrix_a, int[][] matrix_b) {
int[][] result = new int[matrix_a.length][matrix_a[0].length];
class AddWorker implements Runnable {
int row_number;
AddWorker(int row_number) {
this.row_number = row_number;
}
@Override
public void run() {
for (int i = 0; i < matrix_a[row_number].length; i++) {
result[row_number][i] = matrix_a[row_number][i]
+ matrix_b[row_number][i];
}
latch.countDown();
}
}
executorService.submit(new AddWorker(0));
executorService.submit(new AddWorker(1));
try {
System.out.println("Waiting for Matrix Addition");
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.shutdown();
return result;
}
}
The add() method creates two AddWorker instances. Each instance works on performing addition on one row of the matrix determined by the row_number passed in the constructor. The add() method calls latch.await() which will cause it to block as it is the only thread currently waiting at the latch.
The latch is open when the two worker threads does a countdown on the latch. Two countdowns are required on the latch.
public class CountDownLatchDemo {
public static void main(String[] args) {
int[][] matrix_a = { { 1, 1 }, { 1, 1 } };
int[][] matrix_b = { { 2, 2 }, { 3, 2 } };
MatrixCountDown _matrix = new MatrixCountDown();
int[][] result = _matrix.add(matrix_a, matrix_b);
printMatrix(result);
}
public static void printMatrix(int[][] x) {
for (int[] res : x) {
for (int val : res) {
System.out.print(val + ", ");
}
System.out.println(" ");
}
}
}
The key difference from a similar application written using cyclic barrier would be- Worker threads are not waiting after calling the countdown operations. Only threads that make call to await() operation on the latch wait
- latch is the initialized to the number of countdown operations and not on the number of threads required to wait on it. In case of Cyclic barrier, barrier is initialized with the number of threads that needs to wait at the barrier.
Waiting for Matrix Addition
3, 3,
4, 3,