CyclicBarrier and Count DownLatch in Java

CyclicBarrier and Count DownLatch in Java

CyclicBarrier and CountDownLatch are both synchronization aids in Java’s java.util.concurrent package, but they serve different purposes and have distinct functionalities.

CyclicBarrier and Count DownLatch

CountDownLatch

  1. Purpose: CountDownLatch is used to make one or more threads wait until a set of operations being performed in other threads completes.
  2. Functionality: It has a counter that is decremented by calling the countDown() method. When the counter reaches zero, the threads waiting on the latch are released.
  3. Reusability: It is a one-time use synchronization aid. Once the count reaches zero, it cannot be reset or reused CyclicBarrier and Count DownLatch.
  4. Usage: Suitable for situations where you want to wait for a set of operations to complete (e.g., waiting for all services to start before starting the main application).

CyclicBarrier

  • Purpose: CyclicBarrier is used to make a group of threads wait for each other to reach a common barrier point.
  • Functionality: It allows a set of threads to wait for each other to reach a common barrier point before proceeding. The barrier is called cyclic because it can be reused after the waiting threads are released.
  • Reusability: It can be reused after the waiting threads are released, hence suitable for cyclic barriers.
  • Usage: Suitable for scenarios where threads need to wait for each other to reach a certain point before proceeding (e.g., multi-phase computations where threads must synchronize at the end of each phase).

Example
Example
Using CountDownLatch

java
import java.util.concurrent.CountDownLatch;

class Worker extends Thread {
    private final CountDownLatch latch;

    public Worker(CountDownLatch latch) {
        this.latch = latch;
    }

    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " is working.");
            Thread.sleep(1000); // Simulate work
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            latch.countDown();
            System.out.println(Thread.currentThread().getName() + " has finished.");
        }
    }
}

public class CountDownLatchExample {
    public static void main(String[] args) {
        final int threadCount = 3;
        CountDownLatch latch = new CountDownLatch(threadCount);

        for (int i = 0; i < threadCount; i++) {
            new Worker(latch).start();
        }

        try {
            latch.await(); // Wait for all workers to finish
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("All workers have finished. Proceeding with main thread.");
    }
}


CyclicBarrier

java
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

class Task extends Thread {
    private final CyclicBarrier barrier;

    public Task(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " is waiting at the barrier.");
            barrier.await(); // Wait at the barrier
            System.out.println(Thread.currentThread().getName() + " has crossed the barrier.");
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

public class CyclicBarrierExample {
    public static void main(String[] args) {
        final int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, new Runnable() {
            @Override
            public void run() {
                System.out.println("All parties have arrived at the barrier. Let's proceed.");
            }
        });

        for (int i = 0; i < threadCount; i++) {
            new Task(barrier).start();
        }
    }
}

Explanation CyclicBarrier and Count DownLatch

1. Using CountDownLatch:

  1. Three Worker threads are created and started.
  2. Each Worker thread performs some work (simulated by Thread.sleep(1000)) and then calls countDown() to decrement the latch count.
  3. The main thread calls await() on the latch and waits until all Worker threads have finished.
  4. Once the count reaches zero, the main thread proceeds CyclicBarrier and Count DownLatch.

2. Using CyclicBarrier:

  • Three Task threads are created and started.
  • Each Task thread waits at the barrier by calling await().
  • When all threads reach the barrier, the barrier action (a Runnable that prints a message) is executed.
  • After the barrier action, all threads proceed with their execution.

Homepage

Readmore