/**
设置成员变量 state =2
**/
CountDownLatch countDownLatch = new CountDownLatch(2);
public CountDownLatch(int count)
{
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
Sync 内部类源码
private static final class Sync extends AbstractQueuedSynchronizer
{
private static final long serialVersionUID = 4982264981922014374L;
Sync(int count)
{
setState(count);
}
int getCount()
{
return getState();
}
// 调用await()方法中会用到
protected int tryAcquireShared(int acquires)
{
return (getState() == 0) ? 1 : -1;
}
/**
计数器-1
**/
protected boolean tryReleaseShared(int releases)
{
// Decrement count; signal when transition to zero
for (;;)
{
// 获取state的值 如果是0 表示没有值可减了
int c = getState();
if (c == 0)
// state -1 失败 结束死循环
return false;
// 要更新的值
int nextc = c-1;
// CAS 更新state 更新成功
if (compareAndSetState(c, nextc))
//判断nextc 值是否等于 0 如果等于0 返回true
// 不等于0 返回false
//结束死循环
return nextc == 0;
}
}
}
countDown()
public void countDown() {
sync.releaseShared(1);
}
AQS releaseShared
public final boolean releaseShared(int arg)
{
/**
tryReleaseShared 返回值是true 表示state刚好是由1-1 = 0 的时候
其他情况是false
**/
if (tryReleaseShared(arg))
{
// aqs 类中定义的方法
doReleaseShared();
return true;
}
// 计数器-1 失败
return false;
}
doReleaseShared
private void doReleaseShared() {
/**
当线程把state 从1-0的线程会执行这个方法 唤醒 因为执行await方法阻塞的线程
**/
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;
}
}
await 阻塞线程方法
public void await() throws InterruptedException
{
sync.acquireSharedInterruptibly(1);
}
aqs 中定义acquireSharedInterruptibly
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException
{
if (Thread.interrupted())
// 如果线程中断了 抛出异常
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
// 判断state 的值 执行的是 countDownLatch 中自己定义的方法
// state>0 返回-1 state=0 返回1
// 当tryAcquireShared 返回-1执行doAcquireSharedInterruptibly方法
doAcquireSharedInterruptibly(arg);
}
aqs中定义 doAcquireSharedInterruptibly
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;
}
}
// CAS 设置首节点的waitStatus=-1 为啥要设置是释放锁的时候 会判断
// 要唤醒的线程的waitStatus 是否是-1
if (shouldParkAfterFailedAcquire(p, node) &&
// 这里线程会被阻塞 就是代码卡住在这里不会在执行了
parkAndCheckInterrupt())
throw new InterruptedException();
}
}
finally
{
if (failed)
cancelAcquire(node);
}
}
shouldParkAfterFailedAcquire 阻塞线程
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node)
{
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
setHeadAndPropagate 等待队列中的线程如何唤醒的?
private void setHeadAndPropagate(Node node, int propagate)
{
// propagate =1 node 第一个节点
Node h = head; // Record old head for check below
// 新节点成为头节点
setHead(node);
/*
* Try to signal next queued node if:
* Propagation was indicated by caller,
* or was recorded (as h.waitStatus either before
* or after setHead) by a previous operation
* (note: this uses sign-check of waitStatus because
* PROPAGATE status may transition to SIGNAL.)
* and
* The next node is waiting in shared mode,
* or we don't know, because it appears null
*
* The conservatism in both of these checks may cause
* unnecessary wake-ups, but only when there are multiple
* racing acquires/releases, so most need signals now or soon
* anyway.
*/
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared())
// 递归唤醒线程
doReleaseShared();
}
}