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.
