Detailed Explanation of CountDownLatch, CyclicBarrier, and Semaphore in Java
Detailed Explanation of CountDownLatch, CyclicBarrier, and Semaphore in Java
1. Basic Concepts and Roles
CountDownLatch, CyclicBarrier, and Semaphore are commonly used synchronization utility classes in the JUC package, designed to coordinate the execution order among multiple threads or manage resource allocation:
- CountDownLatch: Allows one or more threads to wait for other threads to complete their operations before proceeding.
- CyclicBarrier: Enables a group of threads to wait for each other; once all threads reach the barrier point, they continue execution simultaneously. It is reusable.
- Semaphore: Controls the number of threads that can access a specific resource concurrently, implementing rate limiting through permits.
2. Detailed Explanation of CountDownLatch
Core Mechanism
- Initialize with a specified counter (e.g.,
new CountDownLatch(3)). - The counter decrements by 1 when a thread calls
countDown(); threads callingawait()will block until the counter reaches zero.
Use Cases
- The main thread waits for multiple child threads to complete tasks before proceeding (e.g., aggregating results after parallel computation).
- Waiting for all dependent components to initialize during service startup.
Example Code
CountDownLatch latch = new CountDownLatch(2);
// Child threads decrement the counter after completing tasks
new Thread(() -> {
System.out.println("Task 1 completed");
latch.countDown();
}).start();
new Thread(() -> {
System.out.println("Task 2 completed");
latch.countDown();
}).start();
// Main thread waits for all tasks to complete
latch.await();
System.out.println("All tasks completed, main thread continues");
Characteristics: The counter cannot be reset; it is for one-time use only.
3. Detailed Explanation of CyclicBarrier
Core Mechanism
- Initialize with a specified number of threads (e.g.,
new CyclicBarrier(3)) and an optional barrier action (Runnable). - Threads block when calling
await()until the specified number of threads reach the barrier point; then all threads continue execution simultaneously.
Use Cases
- Synchronization in multi-phase tasks (e.g., waiting for all threads to be ready at each stage in parallel computation).
- Simulating concurrent testing (multiple threads triggering operations simultaneously).
Example Code
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("All threads reached the barrier, executing barrier action");
});
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " reached the barrier");
try {
barrier.await(); // Wait for other threads
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " continues execution");
}).start();
}
Characteristics: The counter can be reset (via the reset() method), supporting reuse.
4. Detailed Explanation of Semaphore
Core Mechanism
- Initialize with a specified number of permits (e.g.,
new Semaphore(3)). - Threads acquire permits via
acquire()(blocking if no permits are available) and release permits viarelease().
Use Cases
- Limiting concurrent access to resources (e.g., database connection pools, interface rate limiting).
- Controlling the submission rate of tasks in a thread pool.
Example Code
Semaphore semaphore = new Semaphore(2); // Allow 2 threads to access concurrently
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire(); // Acquire a permit
System.out.println(Thread.currentThread().getName() + " occupied resource");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // Release the permit
System.out.println(Thread.currentThread().getName() + " released resource");
}
}).start();
}
Characteristics: Supports fair/non-fair modes; permits can be dynamically increased or decreased.
5. Comparison of the Three
| Feature | CountDownLatch | CyclicBarrier | Semaphore |
|---|---|---|---|
| Counter Resettable? | No (one-time use) | Yes (reusable) | Yes (permits recyclable) |
| Core Role | Wait for other threads to complete | Threads wait for each other | Control resource access quantity |
| Key Methods | await()/countDown() |
await() |
acquire()/release() |
| Suitable Scenarios | Master-slave collaboration | Multi-phase synchronization | Resource pools, rate limiting |
6. Considerations
- CountDownLatch:
await()can be set with a timeout to avoid indefinite waiting. - CyclicBarrier: The barrier action is executed by the last thread arriving at the barrier.
- Semaphore: The
release()method can be called in any thread, even without callingacquire()first (which may cause the number of permits to exceed the initial value).
By appropriately selecting these three tools, thread synchronization and resource control issues can be efficiently resolved.