首页 > 其他 > 详细

CountDownLatch源码剖析

时间:2021-07-23 11:19:02      阅读:28      评论:0      收藏:0      [点我收藏+]

.

    public static void main(String[] args) throws Exception{
        CountDownLatch latch = new CountDownLatch(2);

        new Thread(()->{
            try {
                Thread.sleep(2000);
                System.out.println("线程1准备执行 countDown 操作");
                latch.countDown();
            }catch (Exception e){
                e.printStackTrace();
            }
        }).start();

        new Thread(()->{
            try {
                Thread.sleep(2000);
                System.out.println("线程2准备执行 countDown 操作");
                latch.countDown();
            }catch (Exception e){
                e.printStackTrace();
            }
        }).start();

        System.out.println("main() 线程准备执行 await");
        latch.await();
        System.out.println("success");
    }

CountDownLatch

  我们在创建 CountDownLatch 的时候,其实他就是一个 sycn 、继承了 aqs,可以猜到它的实现应该也是aps 那一套。首先就是将 count 赋值给了 state 标记锁状态。

技术分享图片

await

  主线程在 await() 的时候就等在了那里,直到所有线程执行完 countDown() , 主线程就继续往下执行。猜想他应该是进入了 aqs 的同步队列,直到其他线程将他唤醒。那我们就看看它的具体实现。

1. tryAcquireShared() 获取 state ,我们初始化的时候设置的是2,那么此时肯定 !=0 。
2. doAcquireSharedInterruptibly() 首先在 addWaiter() 里面死循环两次将 当前线程加入等待队列中。
3. 然后获取到上一个节点 p, 它肯定是一个空的头节点。
4. 然后 tryAcquireShared() 再次判断一下锁占用状态。
5. 此时 r 肯定是>0 的,然后就 p.next=null 将自己从等待队中摘除出来
6. 最后在 parkAndCheckInterrupt() 里面调用 LockSupport.park() 将自己挂起,等待别人的唤醒。

技术分享图片

countDown

1. tryReleaseShared() 先获取 state ,如果 !=0 说明有人持有锁,那就 cas 操作 -1 返回true。
2. doReleaseShared() 首先获取到头节点 h ,肯定不会为空的。
3. 然后如果状态是 Node.SIGNAL 那就 cas 改成 0 。
4. 最后在 unparkSuccessor() 里面获取头节点的下一个节点,也就是我们放在 同步队列 里面的main线程节点,通过 LockSupport.unpark() 唤醒它。

 技术分享图片

 

 

CountDownLatch源码剖析

原文:https://www.cnblogs.com/wlwl/p/15046807.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!