Java源码学习--并发锁05--03--CountDownLatch

CountDownLatch

  • 俗称倒计时,技术锁,并不是为了加锁,而是通过计数达到等待的功能
  • 等待的形式
    1. 让一组线程在全部启动完成之后,在一起执行(先启动的线程需要阻塞等待后启动的线程,直到一组线程全部都启动完成后,再一起执行)
    2. 主线程等待另外一组线程都执行完成之后,再继续执行。

一、重要方法

1. await

  • 流程

    CountDownLatch
        |-> await

            AQS
             |-> acquireSharedInterruptibly

                CountDownLatch
                    |-> tryAcquire

  • 称为等待,也可以称为加锁
  • 代码
    • 源码
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }
    // 带有超时时间的,最终都会转化成毫秒
    public boolean await(long timeout, TimeUnit unit)
        throws InterruptedException {
        return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
    }
    
    • AQS的中断获取共享锁acquireSharedInterruptibly
    public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }
    
    • tryAcquire
     protected int tryAcquireShared(int acquires) {
        return (getState() == 0) ? 1 : -1;
    }
    
  • 理解
    • await是等待,多个线程执行完成之后,才能继续,否则加入到同步队列中,所以tryAcquireShared,当state==0时,表示所有线程已经全部执行完成,再来就直接获取锁,而且是非公平的获取,有可能当前未加入同步队列的线程获取,也有可能是同步队列获取

2. countDown

  • 流程

    CountDownLatch
        |-> countDonw

            AQS
              |-> releaseShared

                    CountDownLatch
                        |-> tryReleaseShared
  • 代码
    • 源码
      • AQS的公共释放共享锁方法
      public final boolean releaseShared(int arg) {
          //此方法是最重要的点,什么时候执行释放锁
          if (tryReleaseShared(arg)) {
              doReleaseShared();
              return true;
          }
          return false;
      }
      
      • CountDownLatch的是否可以释放锁的方法
      protected boolean tryReleaseShared(int releases) {
          // Decrement count; signal when transition to zero
          for (;;) {
              //如果是0,表示已经全部执行,无须继续释放,直接返回false
              int c = getState();
              if (c == 0)
                  return false;
              int nextc = c-1;
              //通过CAS,将state递减
              if (compareAndSetState(c, nextc))
                  return nextc == 0;
          }
      }
      
  • 理解
    • countDown方法,通过使用CAS方法来设置state的值,当值为0,表示所有的任务全部执行完成。

总结

  1. 倒计时充分利用了同步队列等待的原理,将主线程作为需要等待的同步节点,来获取共享锁,当state没有满足条件时,就会一直阻塞在同步队列中,使用countdown之后,如果state0,表示所有的任务执行完成,即让同步队列的第一个节点开始执行,即主线程。所以只有当state0时,才表示执行完成,此处没有显示枷锁的操作,await方法就是将主线程加入到同步对列中,利用其阻塞的特性,达到倒计时的功能,其他线程相当于抢到锁的线程,其他线程执行完成之后,才会释放同步队列的第一个节点,让其执行,即主线程执行。
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页