CountDownLatch源码解析

一.构造器解析

首先,CountDownLatch会通过构造函数为state赋值,state在这里充当计数器的角色

1.new 构造函数,通过构造函数给计数器赋值

CountDownLatch源码解析_第1张图片

2.给state赋值

CountDownLatch源码解析_第2张图片

3.state完成赋值

在这里插入图片描述
state和之前分析AQS有所不同,其代表计数器的含义,AQS中的state代表的是锁状态

二.await源码解析

话不多说,开始await的源码解析,我将以画图的形式来解析

1.调用apiCountDownLatch源码解析_第3张图片#### 2.点开上一步中的await可以得到以下图

CountDownLatch源码解析_第4张图片
CountDownLatch源码解析_第5张图片
CountDownLatch源码解析_第6张图片

3.分析tryAcquireShared(arg)

在这里插入图片描述
这其实没什么好分析的,获得计数器state的值,判断是否为0,如果是则返回1,否则返回-1
CountDownLatch源码解析_第7张图片

4.现在开始分析doAcquireSharedInterruptibly(arg)

CountDownLatch源码解析_第8张图片①首先分析第一行代码addWaiter(Node.SHARED)
CountDownLatch源码解析_第9张图片
我解释两个地方:
1.mode传进来的是share节点:static final Node SHARED = new Node();并通过Node的构造函数将nextWaiter指向mode,代码如下:

	 Node(Thread thread, Node mode) {     // Used by addWaiter
            this.nextWaiter = mode;
            this.thread = thread;
        }

2.tail的代码如下,在源代码中未赋值,所以为null

private transient volatile Node tail;

接上继续分析,enq(Node)分析
CountDownLatch源码解析_第10张图片CountDownLatch源码解析_第11张图片
粗略的画了一张由上面代码生成节点的图,希望可以使你更好的理解上面的代码
②.分析下面代码
CountDownLatch源码解析_第12张图片CountDownLatch源码解析_第13张图片现在我将分析上图中第四步中的代码:分段分析,第一段
CountDownLatch源码解析_第14张图片在countDownLatch中主要用到了两个功能,一个是将node节点的上一个节点通过CAS原子操作将ws设置为-1即Node.SIGNAL
第二个功能主要是判断pred中的ws是否为-1,若是返回true,继续执行第二段,现在开始分析第二段:parkAndCheckInterrupt()
在这里插入图片描述到这里为止,调用await的线程被挂起,现在分析countDown源码

二.countDown源码解析

1.api调用

在这里插入图片描述

2.分析countDown

CountDownLatch源码解析_第15张图片

在这里首先分析tryReleaseShared(arg)
CountDownLatch源码解析_第16张图片
这里的功能很简单,希望读者可以自己思考

3.现在开始分析doReleaseShared()

CountDownLatch源码解析_第17张图片
CountDownLatch源码解析_第18张图片
分析到这里则要去分析await被挂起的那里了,现在开始从await线程被挂起的那里继续分析

三.在await处线程被挂起处继续分析

现在回到线程被挂起的地方
在这里插入图片描述在这里插入图片描述
CountDownLatch源码解析_第19张图片
分析一下setHeadAndPropagate
CountDownLatch源码解析_第20张图片至此,CountDownLatch源码的分析已基本结束,在这里我并未很全面的去解析,目的也是为了使读者可以去探索一些。
其实在分析完AQS源码后,再看这里,有很多相同之处,也相对简单,希望读者可以自己跟着我的这篇博客实际动手分析一遍,希望对你有帮助,这篇博客基本分析了大概原理,希望抛砖引玉,使读者更加深入全面的理解CountDownLatch的原理

你可能感兴趣的:(JUC,java)