What is CountDownLatch vs semaphore in Java?

Shelly 118 Published: 11/04/2024

What is CountDownLatch vs semaphore in Java?

In Java, both CountDownLatch and Semaphore are used to control access to a common resource or to coordinate the actions of multiple threads. However, they serve different purposes and have distinct characteristics.

CountDownLatch

A CountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. It's like a gatekeeper that ensures a certain condition is met before allowing access.

Here's how it works:

You create a CountDownLatch with a specified count (usually 1). When the latch is created, its count is set to the initial value. The latch can be counted down by calling the countDown() method, which decrements the count. Once the count reaches zero, all threads waiting on the latch will be released and allowed to proceed.

Use cases for CountDownLatch include:

Ensuring a specific number of tasks are completed before proceeding. Implementing a "done" signal between threads or processes. Coordinating the start of multiple threads or processes.

Semaphore

A Semaphore is a binary semaphore that allows only a specified number of threads to access a common resource at a time. It's like a ticket booth where a limited number of people can enter, and once those slots are taken, others must wait.

Here's how it works:

You create a Semaphore with a specified number of permits (usually greater than 0). When a thread acquires the semaphore using the acquire() method, it takes one permit. If there are no available permits, the thread will block until a permit becomes available. Once a thread releases a permit by calling the release() method, another waiting thread can acquire the permit.

Use cases for Semaphore include:

Limiting concurrent access to a shared resource. Implementing a "lock" mechanism where only a certain number of threads can access the locked resource at a time. Controlling the flow of tasks or jobs in a multi-threaded environment.

Key differences

In summary:

CountDownLatch is used to coordinate the completion of a set of operations, whereas Semaphore is used to control concurrent access to a shared resource. CountDownLatch allows one or more threads to wait until a condition is met, while Semaphore allows only a specified number of threads to access a resource at a time.

In Java, choosing between CountDownLatch and Semaphore depends on your specific use case. If you need to coordinate the completion of tasks, CountDownLatch might be more suitable. If you need to limit concurrent access to a shared resource, Semaphore is likely the better choice.

Java CountDownLatch increment

I'll respond in English for this special occasion!

The CountDownLatch class in Java is a synchronization tool that allows one or more threads to wait at a specific point until a set of operations being performed in other threads has completed.

To increment the count of a CountDownLatch, you can simply call its countDown() method. This method decrements the latch's internal counter by 1, indicating that one operation has been completed.

Here's an example of how to use CountDownLatch:

import java.util.concurrent.CountDownLatch;

public class Main {

public static void main(String[] args) throws InterruptedException {

// Create a CountDownLatch with a count of 3

final CountDownLatch latch = new CountDownLatch(3);

// Start three threads, each waiting for the latch to be counted down to 0

Thread t1 = new Thread(() -> {

try {

latch.await(); // Wait until the latch is counted down to 0

System.out.println("Thread 1: Latch is counted down to 0");

} catch (InterruptedException e) {

throw e;

}

});

t1.start();

Thread t2 = new Thread(() -> {

try {

// Simulate some operation taking place

Thread.sleep(2000);

System.out.println("Thread 2: Operation completed");

latch.countDown(); // Decrement the count of the latch by 1

System.out.println("Thread 2: Counted down");

} catch (InterruptedException e) {

throw e;

}

});

t2.start();

Thread t3 = new Thread(() -> {

try {

// Simulate some operation taking place

Thread.sleep(1000);

System.out.println("Thread 3: Operation completed");

latch.countDown(); // Decrement the count of the latch by 1

System.out.println("Thread 3: Counted down");

} catch (InterruptedException e) {

throw e;

}

});

t3.start();

// Simulate some operation taking place

Thread.sleep(2000);

System.out.println("Main thread: Operation completed");

latch.countDown(); // Decrement the count of the latch by 1

t1.join();

t2.join();

t3.join();

}

}

In this example, we create a CountDownLatch with a count of 3 and start three threads. Each thread calls await() to wait for the latch to be counted down to 0.

We then simulate some operations taking place in each thread and use countDown() to decrement the count of the latch by 1.

The main thread also simulates an operation taking place and uses countDown() to decrement the count of the latch by 1, causing all threads waiting at the latch to be released.

When you run this program, you'll see that the output depends on the order in which the operations are completed. The first thread will only be released when the count is 0, while the other two threads can be released earlier if their operations complete before the main thread's operation.

This demonstrates how CountDownLatch can help coordinate multiple threads performing independent operations.