AQS---CountDownLatch
概述
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
CountDownLatch是一种线程同步工具 :允许其他线程阻塞等待,直到正在执行的线程完成;
A {@code CountDownLatch} is initialized with a given <em>count</em>.
CountDownLatch需要一个count进行初始化
The {@link #await await} methods block until the current count reaches zero due to invocations of the {@link #countDown} method, after which all waiting threads are released and any subsequent invocations of {@link #await await} return immediately.
调用await方法将会被阻塞 直到 调用countDown方法让count=0,
A {@code CountDownLatch} is a versatile synchronization tool and can be used for a number of purposes.
CountDownLatch是一个多功能同步工具,可以用于不同的目的;
A {@code CountDownLatch} initialized with a count of one serves as a simple on/off latch, or gate: all threads invoking {@link #await await} wait at the gate until it is opened by a thread invoking {@link #countDown}.
初始化count=1的CountDownLatch 可以当做一个简易开关:所有线程调用await将被阻塞等待 直到 正在执行的线程调用countDown;
A {@code CountDownLatch} initialized to N can be used to make one thread wait until N threads have completed some action, or some action has been completed N times.
初始化count=n的CountDownLatch 可以当做 一个线程阻塞等待 直到其他n个线程完成(或其他线程完成n次);
A useful property of a {@code CountDownLatch} is that it doesn't require that threads calling {@code countDown} wait for the count to reach zero before proceeding, it simply prevents any thread from proceeding past an {@link #await await} until all threads could pass.
public class CountDownLatch {
private static final class Sync extends AbstractQueuedSynchronizer {
}
private final Sync sync;
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
/**
* Causes the current thread to wait until the latch has counted down to zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
* 造成当前线程阻塞等待 直到 latch的count=0,除非线程被中断
* @throws InterruptedException
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/**
* Decrements the count of the latch, releasing all waiting threads if the count reaches zero.
* 减少latch的count,如果count=0将释放所有等待的线程
*
* If the current count is greater than zero then it is decremented.
* 如果当前count>0 将会递减
* If the new count is zero then all waiting threads are re-enabled for thread scheduling purposes.
* 如果count=0 ,所有等待线程将被重新调度
*/
public void countDown() {
sync.releaseShared(1);
}
}
使用场景
线程同步工具 :允许其他线程阻塞等待,直到正在执行的线程完成;
典型用法:
将一个程序分为n个互相独立的可解决任务,并创建值为n的CountDownLatch。
当每一个任务完成时,都会在这个锁存器上调用countDown,等待问题被解决的任务调用这个锁存器的await,将他们自己拦住,直至锁存器计数结束;
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(3);
Task task = new Task(countDownLatch);
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
Thread t3 = new Thread(task);
t1.start();
countDownLatch.await(1, TimeUnit.SECONDS);
t2.start();
countDownLatch.await(1, TimeUnit.SECONDS);
t3.start();
countDownLatch.await(1, TimeUnit.SECONDS);
}
static class Task implements Runnable{
private CountDownLatch countDownLatch;
Task(CountDownLatch countDownLatch){
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 正在执行任务");
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName() + " 任务结束,countDown");
}
public CountDownLatch getCountDownLatch() {
return countDownLatch;
}
public void setCountDownLatch(CountDownLatch countDownLatch) {
this.countDownLatch = countDownLatch;
}
}
结果:
Thread-0 正在执行任务
Thread-0 任务结束,countDown
Thread-1 正在执行任务
Thread-1 任务结束,countDown
Thread-2 正在执行任务
Thread-2 任务结束,countDown
实现思路
继承AQS,以共享模式访问共享资源,对指定的count进行cas操作;
链路
new CountDownLatch(3)
/**
* new CountDownLatch(3) 初始化AQS的state
*
* java.util.concurrent.CountDownLatch#CountDownLatch(int)
* java.util.concurrent.CountDownLatch.Sync#Sync(int)
* java.util.concurrent.locks.AbstractQueuedSynchronizer#setState(int)
*/
await()
// java.util.concurrent.CountDownLatch.await()
/**
* Causes the current thread to wait until the latch has counted down to zero
* await会将当前线程等待 直到 latch的count=0
* @throws InterruptedException
*/
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly
/**
* Acquires in shared mode
*/
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// 如果以共享模式获取失败 -> 当前线程进入阻塞排队
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
// java.util.concurrent.CountDownLatch.Sync.tryAcquireShared
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly
/**
* Acquires in shared interruptible mode.
* @param arg the acquire argument
*/
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final AbstractQueuedSynchronizer.Node node = addWaiter(AbstractQueuedSynchronizer.Node.SHARED);
boolean failed = true;
try {
for (;;) {
final AbstractQueuedSynchronizer.Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
countDown()
// java.util.concurrent.CountDownLatch.countDown
/**
* Decrements the count of the latch, releasing all waiting threads if the count reaches zero.
* latch的count-1
*/
public void countDown() {
sync.releaseShared(1);
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer.releaseShared
/**
* Releases in shared mode.
*/
public final boolean releaseShared(int arg) {
// 如果latch的count-1成功 -> 唤醒队列中正在等待的线程
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
// java.util.concurrent.CountDownLatch.Sync.tryReleaseShared
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
// java.util.concurrent.locks.AbstractQueuedSynchronizer.doReleaseShared
/**
* Release action for shared mode -- signals successor and ensures propagation.
* 以共享模式释放等待的线程
*/
private void doReleaseShared() {
/*
* Ensure that a release propagates, even if there are other
* in-progress acquires/releases. This proceeds in the usual
* way of trying to unparkSuccessor of head if it needs
* signal. But if it does not, status is set to PROPAGATE to
* ensure that upon release, propagation continues.
* Additionally, we must loop in case a new node is added
* while we are doing this. Also, unlike other uses of
* unparkSuccessor, we need to know if CAS to reset status
* fails, if so rechecking.
*/
for (;;) {
AbstractQueuedSynchronizer.Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == AbstractQueuedSynchronizer.Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, AbstractQueuedSynchronizer.Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, AbstractQueuedSynchronizer.Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
浙公网安备 33010602011771号