package java.util.concurrent;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class CountDownLatch {
/**
* Synchronization control For CountDownLatch.
* Uses AQS state to represent count.
*
* 用AbstractQueuedSynchronizer的状态来表示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 (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
private final Sync sync;
// 构造一个等待线程数量为count的闭锁。 注:count的值一旦设定就不可以更改了。
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 interrupted.
*
* If the current count is greater than zero then the current thread becomes disabled for thread scheduling purposes
* and lies dormant until one of two things happen:
* The count reaches zero due to invocations of the {@link #countDown} method;
* Some other thread {@linkplain Thread#interrupt interrupts} the current thread.
*/
// 线程调用await()方法,进入等待状态。
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// -------------------- 补充:AbstractQueuedSynchronizer 中的方法 ----------------------------------------
//
// public final void acquireSharedInterruptibly(int arg) throws InterruptedException {
// if (Thread.interrupted())
// throw new InterruptedException();
// if (tryAcquireShared(arg) < 0) // 获取锁失败
// doAcquireSharedInterruptibly(arg);
// }
//
// private void doAcquireSharedInterruptibly(int arg) throws InterruptedException {
// final Node node = addWaiter(Node.SHARED);
// boolean failed = true;
// try {
// 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);
// }
// }
//
// -------------------- 补充:AbstractQueuedSynchronizer 中的方法 ----------------------------------------
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
/**
* Decrements the count of the latch, releasing all waiting threads if the count reaches zero.
* If the current count equals zero then nothing happens.
*/
public void countDown() {
sync.releaseShared(1);
}
// -------------------- 补充:AbstractQueuedSynchronizer 中的方法 ----------------------------------------
//
// public final boolean releaseShared(int arg) {
// if (tryReleaseShared(arg)) {
// doReleaseShared();
// return true;
// }
// return false;
// }
//
// 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 (;;) {
// Node h = head;
// if (h != null && h != tail) {
// int ws = h.waitStatus;
// if (ws == Node.SIGNAL) {
// if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
// continue; // loop to recheck cases
// unparkSuccessor(h);
// }
// else if (ws == 0 &&
// !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
// continue; // loop on failed CAS
// }
// if (h == head) // loop if head changed
// break;
// }
// }
//
// -------------------- 补充:AbstractQueuedSynchronizer 中的方法 ----------------------------------------
/**
* Returns the current count.
*/
public long getCount() {
return sync.getCount();
}
}
CountDownLatch源码分析
最新推荐文章于 2020-11-04 16:19:17 发布