CountDownLatch
is a Java concurrency package () in a synchronization helper class that allows one or more threads to wait for a set of operations to complete.
I. Design Concept
CountDownLatch
is based on the AQS (AbstractQueuedSynchronizer) implementation. The core idea is thatMaintaining a countdownThe threads that are waiting will continue to execute each time the countdown decreases to zero. Its main design goal is to allow multiple threads to coordinate the completion of a set of tasks.
1. Constructors and counters
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
= new Sync(count);
}
tectonic (geology)CountDownLatch
incomingcount
determines the initial value of the counter. This counter controls the release of the thread.
2. Core operations supported by AQS
AQS YesCountDownLatch
The basis for this is through customizing the inner classSync
Realization.Sync
inherits from AQS and provides the necessary methods. The following are the key operations:
-
acquireShared(int arg)
: If the counter value is zero, it means that all tasks have been completed and the thread will be licensed. -
releaseShared(int arg)
: Each call tocountDown()
The AQS will reduce the counter, and when the counter drops to zero, the AQS will release all waiting threads.
3. Realization details
-
countDown()
: CallreleaseShared()
Decreases the counter and notifies the waiting thread. -
await()
: CallacquireSharedInterruptibly(1)
If the counter is non-zero, it blocks and waits.
II. Underlying principles
CountDownLatch
The core of the program is based onAbstractQueuedSynchronizer
(AQS) to manage counter state.AQS is the basis for many synchronization tools in JUC, enabling thread management and scheduling through a synchronized queue in exclusive/shared mode.CountDownLatch
The use of AQSshared locking mechanismto control multiple threads waiting for a condition.
1. AQS sharing model
AQS is designed with two modes of synchronization:Exclusive mode(exclusive) andshared model(shared)。CountDownLatch
Use the shared model:
-
Exclusive mode: Only one thread can hold the lock at a time, as in
ReentrantLock
。 -
shared model: Allows multiple threads to share lock state, such as the
Semaphore
cap (a poem)CountDownLatch
。
CountDownLatch
(used form a nominal expression)await()
cap (a poem)countDown()
method corresponds to the AQSacquireShared()
cap (a poem)releaseShared()
Operation.acquireShared()
Will check the synchronization status (counter value), if the status is zero then return immediately, otherwise block the current thread and enter the waiting queue.releaseShared()
Used to reduce the counter and wake up all waiting threads.
2. Design of Sync internal classes
CountDownLatch
Through a private inner classSync
to implement the synchronization logic.Sync
inherited fromAQS
and rewritetryAcquireShared(int arg)
cap (a poem)tryReleaseShared(int arg)
Methods.
static final class Sync extends AbstractQueuedSynchronizer {
Sync(int count) {
setState(count);
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// spin-down counter
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c - 1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
- tryAcquireShared(int): Returns 1 (successful lock acquisition) when the counter is zero, otherwise returns -1 (blocking).
-
tryReleaseShared(int): Each time
countDown()
Decreases the counter value and returns when the counter reaches zerotrue
that wakes up all blocking threads.
3. CAS operations ensure thread safety
tryReleaseShared
method uses CAS (compare-and-set) to update the counter, avoiding the overhead of locks.CAS operations are performed by CPU primitives such ascmpxchg
instructions) support, enabling efficient non-blocking operations. This design ensures that thecountDown()
of thread safety, allowing multiple threads to concurrently reduce the counter.
4. Internal ConditionObject
CountDownLatch
reuse is not supported because AQS'sConditionObject
is designed as a single trigger mode. Once the counter drops to zero, theCountDownLatch
It can't be reset, you can only release all threads without setting the initial counter value again. This is the root cause of its non-reusability.
III. Application scenarios
-
Waiting for multi-threaded tasks to complete:
CountDownLatch
Commonly used in scenarios where you need to wait for a group of threads to complete their tasks before continuing, such as batch processing tasks. - Parallel execution re-summarization: In some data analysis or computationally intensive tasks, the task is split into multiple subtasks to be executed in parallel, and the main thread waits for all subtasks to complete before summarizing the results.
-
Multi-service dependency coordination: When a service depends on multiple other services, you can use the
CountDownLatch
to synchronize calls to individual services and ensure that all dependent services are ready before executing the main task.
IV. Sample code
The following example shows how to use theCountDownLatch
Implement a mechanism for a concurrent task to wait for all subtasks to complete.
import ;
public class CountDownLatchExample {
private static final int TASK_COUNT = 5;
private static CountDownLatch latch = new CountDownLatch(TASK_COUNT);
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < TASK_COUNT; i++) {
new Thread(new Task(i + 1, latch)).start();
}
// The main thread waits for all tasks to complete
();
("All tasks have been completed,Continuation of main thread tasks");
}
static class Task implements Runnable {
private final int taskNumber;
private final CountDownLatch latch;
Task(int taskNumber, CountDownLatch latch) {
= taskNumber;
= latch;
}
@Override
public void run() {
try {
("subtask " + taskNumber + " commence");
((int) (() * 1000)); // Simulation of task execution time
("subtask " + taskNumber + " fulfillment");
} catch (InterruptedException e) {
().interrupt();
} finally {
(); // fulfillment一个任务,Counter minus one
}
}
}
}
V. Comparison with other synchronization tools
1. CyclicBarrier
Principles and Uses:
-
CyclicBarrier
It also allows a group of threads to wait for each other until all threads reach the barrier point. - It is suitable for use inmultistage taskmaybeStaged Convergence, such as summarizing results at each stage when dealing with chunked calculations.
underlying implementation:
-
CyclicBarrier
Internally throughReentrantLock
cap (a poem)Condition
implementation, the barrier count can be reset, thus supporting recycling.
Comparison with CountDownLatch:
-
CyclicBarrier
(used form a nominal expression)reusabilitymakes it suitable for repetitive synchronization scenarios, whileCountDownLatch
It's a one-time thing. -
CountDownLatch
More flexible, allowing arbitrary thread callscountDown()
, suitable for distributed tasks.CyclicBarrier
Requires the specified thread to reach the barrier.
2. Semaphore
Principles and Uses:
-
Semaphore
mainly used forControlling access to resourcesof concurrency, such as limiting access to a database connection pool.
underlying implementation:
-
Semaphore
A shared schema implementation based on AQS, similar to theCountDownLatch
The "License" number is the number of "licenses" that are allowed to control the resources.
Comparison with CountDownLatch:
-
Semaphore
Licenses can be dynamically increased/decreased, whileCountDownLatch
Only decreasing. -
Semaphore
suitable for controlling access restrictions, whileCountDownLatch
Used for synchronizing point countdown.
3. Phaser
Principles and Uses:
-
Phaser
beCyclicBarrier
enhancement that allows the number of participating threads to be dynamically adjusted. - Ideal for multi-stage task synchronization with the ability to increase or decrease participating threads at any time.
underlying implementation:
-
Phaser
An internal counter is included to manage the participating threads in the current phase, allowing tasks to be dynamically registered or logged off.
Comparison with CountDownLatch:
-
Phaser
Better suited to complex scenarios, with the ability to flexibly control stages and participation threads;CountDownLatch
has a simple structure and can only be used for one-time synchronization. -
Phaser
is designed to be more complex for long, multi-threaded coordination tasks, while theCountDownLatch
Better for simple tasks waiting.
4. Summary
CountDownLatch
is a lightweight, non-reusable countdown synchronizer for simple one-time thread coordination. Its AQS-based shared locking implementation allows for efficient concurrency in thread waiting and counter updating. AlthoughCountDownLatch
Not reusable, but its clean design makes it especially suitable for scenarios where you need to wait for a multi-threaded task to complete.
Compared to other JUC tools:
-
CyclicBarrier
It is more suitable for multi-stage synchronization and stage summarization tasks. -
Semaphore
Suitable for resource access control with a controlled amount of licenses. -
Phaser
Higher flexibility for dynamic participation in threads, complex multi-stage tasks.
Choosing the right synchronization tool depends on the nature of the task, the dynamics of thread involvement, and the need to reuse synchronization controls.