zoukankan      html  css  js  c++  java
  • CountDownLatch源码剖析

      CountDownLatch 计数器设置默认的 count ,然后调用 await() 的线程会一直被挂起,直到 count 个线程都执行 countDown() 之后,被挂起的线程才会唤醒,接着走下面的逻辑。

        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() 里面for循环中循环两次将 当前线程加入等待队列中。
    3. 然后获取到上一个节点 p, 它肯定是一个空的头节点。
    4. 然后 tryAcquireShared() 再次判断一下锁占用状态。
    5. setHeadAndPropagate() 将当前节点设置为头节点(因为可能不止一个地方吊桶 await() ,所以通过指针的变化一个个遍历出来)
    6. 此时 r 肯定是>0 的,然后就 p.next=null 将自己从等待队中摘除出来
    7. 最后在 parkAndCheckInterrupt() 里面调用 LockSupport.park() 将自己挂起,等待别人的唤醒。

    countDown

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

     

  • 相关阅读:
    js点击显示全部内容(用于内容比较长时)
    vs中运行时如何去除虚拟目录
    selenium使用中的几个问题
    解决播客程序不能播放Flv文件的问题
    VS2005 + VSS6.0 简单应用示例
    IList转换为DataTable
    asp.net根据生日计算年龄(具体到年月天)
    vs2005菜单中没有显示源代码管理怎么办
    asp.net解决中文乱码问题
    跨域删除cookie的问题
  • 原文地址:https://www.cnblogs.com/wlwl/p/15046807.html
Copyright © 2011-2022 走看看