jdk 源码分析(15)java CountDownLatch 源码解析

本文深入讲解了CountDownLatch的实现原理,包括其与ReentrantLock的相似之处与不同之处,并详细解释了CountDownLatch如何通过调用AbstractQueuedSynchronizer来管理等待线程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CountDownLatch 和CyclicBarrier 和  Semaphore 在使用的时候有类似,底层实现也很相似的。将分布介绍一下,

CountDownLatch 和lock的机制很相似,(参考lock:jdk 源码分析(7)java ReentrantLock结构)
相同点:
1)lock需要队列保存竞争的线程, CountDownLatch需要队列(链表)保持等待的线程线程,
2)都需要park和unpark。
不同点:
1)lock (重入锁)是争论的谁能将state 变成1,而 CountDownLatch 是大家一起齐心协力将state 变成0,
2) lock 是改变不了state的线程park,而 CountDownLatch 是需要等待的线程park,
3) lock的upark 是另一个线程不再使用state时,选择队列的第一个线程park,而 CountDownLatch是其他线程一起将state 从一个非零值变成零后 park.

1)CountDownLatch    最后是改变 的AbstractQueuedSynchronizer的state 和lock 一样
public CountDownLatch(int count) {
    if (count < 0) throw new IllegalArgumentException("count < 0");
    this.sync = new Sync(count);
}

1) CountDownLatch
await()方法主要调用这个方法,一般await用来暂停需要等待的线程(比如主线程)
     
     
  1. private void doAcquireSharedInterruptibly(int arg)
  2. throws InterruptedException {
  3.         //首先会添加到链表中,这里会记录当前线程,方法取消等待时能找到位置。
  4. final Node node = addWaiter(Node.SHARED);
  5. boolean failed = true;
  6. try {
  7. for (;;) {
  8. final Node p = node.predecessor();
  9. if (p == head) {
  10. int r = tryAcquireShared(arg);
  11. if (r >= 0) {
  12. setHeadAndPropagate(node, r);
  13. p.next = null; // help GC
  14. failed = false;
  15. return;
  16. }
  17. }
  18.                 //让当前线程进入等待,使用supportLock.park 方法
  19. if (shouldParkAfterFailedAcquire(p, node) &&
  20. parkAndCheckInterrupt())
  21. throw new InterruptedException();
  22. }
  23. } finally {
  24. if (failed)
  25. cancelAcquire(node);
  26. }
  27. }

countDown 方法: 
     
     
  1. public final boolean releaseShared(int arg) {
  2.         //这里主要是判断是否已经达release 要求,
  3. if (tryReleaseShared(arg)) {
  4.             //释放park
  5. doReleaseShared();
  6. return true;
  7. }
  8. return false;
  9. }
细看上面里面的实现:
tryReleaseShared : 每次会减少1,一直到==0 否则都是范围false,false 就不会执行 doReleaseShared ();
     
     
  1. protected boolean tryReleaseShared(int releases) {
  2. // Decrement count; signal when transition to zero
  3.             //这里采用了循环,这是乐观锁的一种实现,一直尝试,直到成功,
  4. for (;;) {
  5. int c = getState();
  6. if (c == 0)
  7. return false;
  8.                 //   每次会减少1
  9. int nextc = c-1;
  10. if (compareAndSetState(c, nextc))
  11. return nextc == 0;
  12. }
  13. }
最后看看doReleaseShared()
      
      
  1. private void doReleaseShared() {
  2. for (;;) {
  3. Node h = head;
  4. if (h != null && h != tail) {
  5. int ws = h.waitStatus;
  6. if (ws == Node.SIGNAL) {
  7. if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
  8. continue; // loop to recheck cases
  9.                        //h 里面保存了await暂停的线程,直接释放就可以了,完成了等待过程。
  10. unparkSuccessor(h);
  11. }
  12. else if (ws == 0 &&
  13. !compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
  14. continue; // loop on failed CAS
  15. }
  16. if (h == head) // loop if head changed
  17. break;
  18. }
  19. }

CountDownLatch 解析过程结束:

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值