• 中文
    • English
  • 注册
  • 查看作者
  • JAVA concurrency — CyclicBarrier 与 CountDownLatch 源码详解

    概述


    有着相似之处,并且也常常有人将他们拿出来进行比较,这次,笔者试着从源码的角度分别解析这两个类,并且从源码的角度出发,看看两个类的不同之处。

    CountDownLatch

    从字面上来看是一个计数工具类,实际上这个类是用来进行多线程计数的JAVA方法。

    内部的实现主要是依靠
    的共享模式。当一个线程把
    初始化了一个
    之后,其他的线程调用
    就会阻塞住,直到其他的线程一个一个调用
    方法进行
    操作,把
    的值减到0,即把同步锁释放掉,
    才会进行下去。

    Sync

    内部主要还是实现了一个继承自
    的同步器

    源码如下:

    是继承自
    的同步器,这段代码中值得拿出来讨论的有以下几点:

    1. 为什么用state来存储count的数值?

    2. 因为state和count其实上是一个概念,当state为0的时候说明资源是空闲的,当count为0时,说明所有的
      线程都已经完成,所以两者虽然说不是同样的意义,但是在代码实现层面的表现是完全一致的,因此可以将count记录在state中。

    3. 为什么
      不会返回0?

    4. 首先需要解释下
      在AQS中可能的返回值:负数说明是不可以获取共享锁,0说明是可以获取共享锁,但是当前线程获取后已经把所有的共享锁资源占完了,接下来的线程将不会再有多余资源可以获取了,正数则说明了你可以获取共享锁,并且之后还有余量可以给其他线程提供共享锁。然后我们回过来看
      内部的
      ,我们在实现上完全不关注后续线程,后续的资源占用状况,我只要当前状态,那么这个0的返回值实际上是没有必要的。

    5. 为什么
      中的参数不被使用到?

    6. 根据这个类的实现方式,我们可以知道
      的参数一定是1,因为线程的完成一定是一个一个倒数完成的。实际上我们去看
      方法内部调用到了
      方法的时候可以发现他写死了参数为1,所以实际上
      中的参数不被使用到的原因是因为参数值固定为1.

    构造函数和方法

    CyclicBarrier

    从字面上看是循环栅栏,在JAVA中的作用是让所有的线程完成后进行等待,直到所有的线程全部完成,再进行接下来的操作。

    并没有直接继承AQS实现同步,而是借助了可重入锁
    以及
    来完成自己的内部逻辑。

    成员变量

    我们可以看到成员变量中有一个很陌生的类
    ,这个是
    内部声明的一个
    类,作用是帮助区分线程的分组分代,使得
    可以被复用,如果这个简单的解释不能够让你很好地理解的话可以看接下来的源码解析,通过实现来理解它的用途。

    构造函数

    很常规的构造函数,只是简单的初始化成员变量,没有特别的地方。

    核心方法


    的核心方法,就是靠着这个方法来实现线程的统一规划的,其中调用的是内部实现的
    ,我们来看下代码:

    看完这段核心代码之后我们回头再来反思
    的意义,我们已经可以大致的给出使用
    的理由了:

    不同于
    的实现,
    采取了更加复杂的方式,原因便是因为内部涉及到了多线程之间的干预与通信,
    不关心线程的实现与进程,他只是一个计数器,而
    则需要知道线程是否正常的完结,是否被中断,如果用其他的方式代价会比较高,因此,
    的作者通过静态内部类的方式将整个分代的状态共享于多个线程之间,保证每个线程能够获取到栅栏的状态以及能够将自身的状态更好的反馈回去。同时,这种方式便于重置,也使得
    可以高效的重用。至于为什么
    没有用
    修饰,因为类的方法内部全部都上了锁,所以不会出现数据不同步的问题。

    总结


    从使用上来说可能会有一些相似之处,但是在我们看完源码之后我们会发现两者可以说是天差地别,实现原理,实现方式,应用场景均不相同,总结下来有以下几点:

    1. 实现直接依托于

      则是借助了
      以及

    2. 是作为计数器存在的,因此采取了讨巧的设计,源码结构清晰并且简单,同样功能也较为简单;
      则为了实现多线程的掌控,采用了比较复杂的设计,在代码实现上也显得比较弯弯绕绕。

    3. 由于
      采用的实现方式,相比一次性的

      可以多次重复使用

    4. 计数方式的不同:
      采用累加计数,
      则使用倒数计数

  • 0
  • 0
  • 0
  • 30
  • 请登录之后再进行评论

    登录
  • 任务
  • 实时动态
  • 发布
  • 单栏布局 侧栏位置: