CountdownLatch 源码 构造方法publicCountDownLatch(intcount){if(count0)thrownewIllegalArgumentException(count 0);this.syncnewSync(count);}SyncprivatestaticfinalclassSyncextendsAbstractQueuedSynchronizer{privatestaticfinallongserialVersionUID4982264938641297070L;Sync(intcount){setState(count);}intgetCount(){returngetState();}// await调用共享模式尝试获取锁protectedinttryAcquireShared(intacquires){// state 0 返回1获取成功否则-1阻塞return(getState()0)?1:-1;}// countDown调用共享模式释放锁state自减1protectedbooleantryReleaseShared(intreleases){// CAS循环自旋减statefor(;;){intcgetState();if(c0)returnfalse;intnextcc-1;if(compareAndSetState(c,nextc))returnnextc0;}}}countdownpublicvoidcountDown(){sync.releaseShared(1);}releaseSharedpublicfinalbooleanreleaseShared(intarg){if(tryReleaseShared(arg)){doReleaseShared();returntrue;}returnfalse;}tryReleaseSharedprotectedbooleantryReleaseShared(intreleases){for(;;){intcgetState();if(c0)returnfalse;intnextcc-1;if(compareAndSetState(c,nextc))returnnextc0;}}doReleaseShared遍历 AQS 阻塞队列唤醒头部等待节点等待线程被 unpark 唤醒再次执行tryAcquireShared如果 state0返回 1获取共享锁成功退出阻塞逻辑主线程继续执行后续代码privatevoiddoReleaseShared(){for(;;){Nodehhead;if(h!nullh!tail){intwsh.waitStatus;// 头节点标记SIGNAL说明后继需要唤醒if(wsNode.SIGNAL){// CAS重置头节点状态为0防止重复唤醒if(!compareAndSetWaitStatus(h,Node.SIGNAL,0))continue;// 唤醒头节点的后继等待线程主线程unparkSuccessor(h);}// 无等待线程设置PROPAGATE传播标记elseif(ws0!compareAndSetWaitStatus(h,0,Node.PROPAGATE))continue;}// 循环终止条件中途head发生变化说明有新节点被唤醒继续循环传播if(hhead)break;}}awaitpublicvoidawait()throwsInterruptedException{sync.acquireSharedInterruptibly(1);}acquireSharedInterruptiblypublicfinalvoidacquireSharedInterruptibly(intarg)throwsInterruptedException{if(Thread.interrupted())thrownewInterruptedException();if(tryAcquireShared(arg)0)doAcquireSharedInterruptibly(arg);}tryAcquireSharedprotectedinttryAcquireShared(intacquires){return(getState()0)?1:-1;}doAcquireSharedInterruptibly把当前主线程封装成 共享 SHARED 类型 NodeCAS 把节点加入 AQS 阻塞双向链表尾部循环自旋如果当前节点是队列头节点再次调用 tryAcquireShared执行 parkAndCheckInterrupt()调用 LockSupport.park()当前线程挂起卡住不再往下执行等待其他线程 countDown 把 state 降到 0 唤醒privatevoiddoAcquireSharedInterruptibly(intarg)throwsInterruptedException{// 1. 创建共享SHARED类型节点加入队尾finalNodenodeaddWaiter(Node.SHARED);booleanfailedtrue;try{for(;;){// 获取当前节点前驱finalNodepnode.prev;// 如果前驱是头结点有资格尝试获取共享锁if(phead){intrtryAcquireShared(arg);if(r0){// 获取共享锁成功设置新head传播唤醒setHeadAndPropagate(node,r);p.nextnull;// help GCfailedfalse;return;}}// 调整节点waitStatus无资格则park阻塞if(shouldParkAfterFailedAcquire(p,node)parkAndCheckInterrupt())thrownewInterruptedException();}}finally{if(failed)cancelAcquire(node);}}setHeadAndPropagateprivatevoidsetHeadAndPropagate(Nodenode,intpropagate){Nodehhead;// 保存旧头setHead(node);// 当前等待节点晋升为新head清空thread、prev// propagate0 说明还有剩余共享许可需要继续唤醒后继if(propagate0||hnull||h.waitStatus0||(hhead)null||h.waitStatus0){Nodesnode.next;// 如果下一个节点也是共享节点继续唤醒传播if(snull||s.isShared())doReleaseShared();}}getCountpubliclonggetCount(){returnsync.getCount();}总结awaitlatch.await() → sync.acquireSharedInterruptibly(1) → tryAcquireShared 返回 -1 → doAcquireSharedInterruptibly(1) addWaiter(SHARED) 入队 for 自旋 tryAcquireShared 失败 shouldParkAfterFailedAcquire 设置前驱 SIGNAL parkAndCheckInterrupt() 阻塞主线程countdownlatch.countDown() → sync.releaseShared(1) → tryReleaseShared CAS state到0返回true → doReleaseShared() CAS清空head SIGNAL标记 unparkSuccessor 唤醒主线程 等待线程被唤醒回到 doAcquireSharedInterruptibly 自旋 tryAcquireShared 返回 1 setHeadAndPropagate 晋升新 head、传播唤醒 退出阻塞await执行完毕