构造器
public CountDownLatch(int count) {if (count < 0) throw new IllegalArgumentException("count < 0");this.sync = new Sync(count);}
CountDownLatch初始化的时候会创建一个state大于等于0的同步器
await()阻塞方法
public void await() throws InterruptedException {sync.acquireSharedInterruptibly(1);//同步器的共享方法}
public final void acquireSharedInterruptibly(int arg)throws InterruptedException {if (Thread.interrupted())//中断标识throw new InterruptedException();if (tryAcquireShared(arg) < 0)//获取锁,小于0,说明共享锁已经用完了doAcquireSharedInterruptibly(arg);//加入aqs队列}
protected int tryAcquireShared(int acquires) {return (getState() == 0) ? 1 : -1;}
源码可知,线程进来会判断state的值,如果等于0,则直接运行线程,否则加入aqs队列,自旋检查,或者挂起
private void doAcquireSharedInterruptibly(int arg)throws InterruptedException {final Node node = addWaiter(Node.SHARED);//创建等待节点,并将节点加入aqs队列boolean failed = true;try {for (;;) {final Node p = node.predecessor();if (p == head) {//前节点是head节点int r = tryAcquireShared(arg);//去抢占资源if (r >= 0) {//抢占成功setHeadAndPropagate(node, r);//传递依赖p.next = null; // help GCfailed = false;return;}}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())//挂起throw new InterruptedException();}} finally {if (failed)cancelAcquire(node);}}
线程从挂起处被唤醒后setHeadAndPropagate(node, r)去传递唤醒
private void setHeadAndPropagate(Node node, int propagate) {Node h = head; // Record old head for check belowsetHead(node);//当前被唤醒的线程设为headif (propagate > 0 || h == null || h.waitStatus < 0 ||(h = head) == null || h.waitStatus < 0) {Node s = node.next;if (s == null || s.isShared())doReleaseShared();//传递唤醒线程}}
countDown()唤醒线程
public void countDown() {sync.releaseShared(1);}
public final boolean releaseShared(int arg) {if (tryReleaseShared(arg)) {//释放共享锁doReleaseShared();//唤醒aqs队列中等待的队列return true;}return false;}
protected boolean tryReleaseShared(int releases) {// Decrement count; signal when transition to zerofor (;;) {int c = getState();if (c == 0)return false;int nextc = c-1;if (compareAndSetState(c, nextc))//cas去减去1return nextc == 0;//减去完成之后等于0,返回true}}
private void doReleaseShared() {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 casesunparkSuccessor(h);//唤醒排在第一的线程}else if (ws == 0 &&!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))//PROPAGATE:-3表示下一次共享式同步状态获取将会无条件地被传播下去continue; // loop on failed CAS}if (h == head) // loop if head changedbreak;}}
调用countDown()时,cas去state-1,当state为0时候。唤醒aqs队列里的排在第一的队列
