In Java’s concurrent programming, CountDownLatch
and Semaphore
are synchronization aids from the java.util.concurrent
package. Both are used to control thread execution, but they serve different purposes and have different mechanisms.
CountDownLatch
A CountDownLatch
is used to block a thread (or threads) until a set of operations being performed by other threads completes.
It is typically used when:
-
You want one thread to wait for multiple threads to finish.
-
You need a fixed number of signals before proceeding.
How It Works
- Constructed with a count.
countDown()
method decrements the count.await()
blocks the thread until the count reaches zero.
Constructors:
public CountDownLatch(int count)
Parameter: count – the number of times countDown() must be invoked before threads can pass through await().
Throws: IllegalArgumentException if count is negative.
Code language: JavaScript (javascript)
- Methods
Method | Description |
---|---|
void await() |
Causes the current thread to wait until the latch has counted down to zero. |
boolean await(long timeout, TimeUnit unit) |
Causes the current thread to wait until the latch has counted down to zero, or the specified timeout occurs. |
void countDown() |
Decrements the count of the latch. When count reaches zero, all waiting threads are released. |
long getCount() |
Returns the current count. |
Program
This program demonstrates the use of a CountDownLatch
in Java, which is a synchronization aid that allows one or more threads to wait until a set of operations being performed by other threads completes.
//CountDownLatchDemo.java import java.util.concurrent.CountDownLatch; public class CountDownLatchDemo { static class Worker implements Runnable { private final CountDownLatch latch; Worker(CountDownLatch latch) { this.latch = latch; } @Override public void run() { // Simulate some work try { Thread.sleep((long) (Math.random() * 1000)); System.out.println(Thread.currentThread().getName() + " has completed its task"); latch.countDown(); // Signal completion } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) throws InterruptedException { CountDownLatch latch = new CountDownLatch(3); // Initialize with count 3 // Create threads Thread[] threads = new Thread[3]; for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(new Worker(latch)); threads[i].start(); } // Main thread waits for all threads to complete latch.await(); System.out.println("All workers have completed their tasks"); } } /* C:\>javac CountDownLatchDemo.java C:\>java CountDownLatchDemo Thread-0 has completed its task Thread-2 has completed its task Thread-1 has completed its task All workers have completed their tasks C:\>java CountDownLatchDemo Thread-2 has completed its task Thread-1 has completed its task Thread-0 has completed its task All workers have completed their tasks C:\>java CountDownLatchDemo Thread-1 has completed its task Thread-0 has completed its task Thread-2 has completed its task All workers have completed their tasks */
Semaphore
A Semaphore
is a counting synchronization mechanism that controls access to a resource with a limited number of permits.
It is used when:
- You want to limit concurrent access to a resource (like threads accessing a database or printing job).
- You need to implement resource pools, rate limiting, etc.
How It Works
- Created with a number of permits.
- Threads call
acquire()
to get a permit. - Call
release()
when done, returning the permit.
Constructors
public Semaphore(int permits)
Creates a semaphore with the given number of permits and non-fair ordering.
public Semaphore(int permits, boolean fair)
Creates a semaphore with the given number of permits and a fairness policy:
true = FIFO granting of permits.
false = permits can be granted out of order.
Code language: PHP (php)
Methods
Method | Description |
---|---|
void acquire() |
Acquires a permit, blocking if necessary until one is available. |
void acquire(int permits) |
Acquires the given number of permits, blocking if necessary. |
boolean tryAcquire() |
Acquires a permit only if one is available at the time of invocation. |
boolean tryAcquire(long timeout, TimeUnit unit) |
Acquires a permit if available within the given time. |
void release() |
Releases a permit, returning it to the semaphore. |
void release(int permits) |
Releases the given number of permits. |
int availablePermits() |
Returns the current number of permits available. |
int getQueueLength() |
Returns the number of threads waiting to acquire. |
ProgramÂ
This program demonstrates the use of Semaphore
in Java, which is a synchronization tool that controls access to a shared resource by multiple threads. It ensures that a specific number of threads can concurrently access a particular resource, while others wait for a permit to become available.
//SemaphoreDemo.java import java.util.concurrent.Semaphore; public class SemaphoreDemo { static class Worker implements Runnable { private final Semaphore semaphore; Worker(Semaphore semaphore) { this.semaphore = semaphore; } @Override public void run() { try { semaphore.acquire(); // Acquire permit System.out.println(Thread.currentThread().getName() + " is accessing the shared resource"); // Simulate some work Thread.sleep((long) (Math.random() * 1000)); semaphore.release(); // Release permit System.out.println(Thread.currentThread().getName() + " has released the permit"); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { Semaphore semaphore = new Semaphore(2); // Allow 2 permits // Create threads Thread[] threads = new Thread[5]; for (int i = 0; i < threads.length; i++) { threads[i] = new Thread(new Worker(semaphore)); threads[i].start(); } } } /* C:\>javac SemaphoreDemo.java C:\>java SemaphoreDemo Thread-0 is accessing the shared resource Thread-2 is accessing the shared resource Thread-3 is accessing the shared resource Thread-2 has released the permit Thread-0 has released the permit Thread-4 is accessing the shared resource Thread-3 has released the permit Thread-1 is accessing the shared resource Thread-4 has released the permit Thread-1 has released the permit C:\>java SemaphoreDemo Thread-0 is accessing the shared resource Thread-2 is accessing the shared resource Thread-3 is accessing the shared resource Thread-2 has released the permit Thread-3 has released the permit Thread-4 is accessing the shared resource Thread-0 has released the permit Thread-1 is accessing the shared resource Thread-4 has released the permit Thread-1 has released the permit C:\>java SemaphoreDemo Thread-0 is accessing the shared resource Thread-1 is accessing the shared resource Thread-4 is accessing the shared resource Thread-0 has released the permit Thread-1 has released the permit Thread-2 is accessing the shared resource Thread-4 has released the permit Thread-3 is accessing the shared resource Thread-2 has released the permit Thread-3 has released the permit */
Feature | CountDownLatch |
Semaphore |
---|---|---|
Purpose | Waiting for a set of threads to finish or for an event to occur | Controlling access to a shared resource, limiting concurrent access |
Count/Permits | Single count, can only be decremented | Counter of permits, can be incremented or decremented |
Reusability | No, it is a one-time use tool | Yes, reusable over time |
Blocking Behavior | Blocks threads until the count reaches zero | Blocks threads if no permits are available |
State | Countdown state, once it reaches zero, it can’t be reused | Permits are available until released, can be adjusted dynamically |
Thread Coordination | Used to synchronize threads, waiting for all to complete before proceeding | Used to limit the number of threads accessing a shared resource at the same time |
Use Case | Synchronizing threads, such as waiting for workers to complete their tasks | Limiting concurrent access to a resource (e.g., managing a connection pool) |
Acquisition Mechanism | countDown() is used to decrement the count |
acquire() is used to acquire a permit and release() to release a permit |
Post-Completion State | Once count reaches zero, it cannot be reset | Permits can be acquired and released multiple times |
Thread Safety | Ensures that all threads wait for the countdown to reach zero | Ensures limited access to shared resources by controlling the number of concurrent threads |
CountDownLatch and Semaphore are both powerful tools for managing synchronization in concurrent programming in Java, offering different capabilities suited to various synchronization needs.