CountDownLatch中AQS的使用
CountDownLatch 是 JAVA JUC包下提供的一个计数器.主要用于多任务处理中需要同步返回的场景.
主要的方法
方法名 | 描述 |
---|---|
countDown() | 利用CAS操作完成计数器减一计算 |
await() | 阻塞线程 直到计数器到0为止 |
await(long timeout, TimeUnit unit) | 阻塞线程 直到计数器为0 或者执行时间到达timeout |
要学习AQS主要看下await 和 await(timeout,unit) 2个方法 和 Sync内部类
CountDownLatch 内部类 Sync(继承了AQS)
public class CountDownLatch {
/**
* Synchronization control For CountDownLatch.
* Uses AQS state to represent count.
*/
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
/** for循环保证了不停的尝试cas直到成功更新 */
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
/** 利用cas比较内存中的state值是否与期望值c一致
*一致就更新内存中的state值为nextc
*/
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
//to do...
}
countDown方法
public void countDown() {
sync.releaseShared(1);
}
/** AbstractQueuedSynchronizer 父类方法 */
public final boolean releaseShared(int arg) {
/** tryReleaseShared sync子类实现 */
if (tryReleaseShared(arg)) {
/**释放共享锁 实际上在countdownLatch中未用到*/
doReleaseShared();
return true;
}
return false;
}
await方法
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
/** AbstractQueuedSynchronizer类中的方法 */
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
/** tryAcquireShared 子类实现 Sync
* 发现计数器未到0 返回-1 执行
* doAcquireSharedInterruptibly
*/
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
/**阻塞线程 不停的尝试获取state状态 直到为0 */
for (;;) {
final 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);
}
}
await(timeout,unit) 方法
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
/** AbstractQueuedSynchronizer类中的方法 */
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
/** 这里不同的是 多了个或条件
* 如果state减为0 返回true
* 或者执行doAcquireSharedNanos
*/
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
}
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
/** 计算超时时间 */
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
/** 在未超时情况下不停尝试获取state状态 */
for (;;) {
final 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 true;
}
}
nanosTimeout = deadline - System.nanoTime();
/** 超时情况 不用管state状态 直接从阻塞状态跳出 */
if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}