JUC 系列:AQS -->学习 Doug Lea 大神思想
Posted offerNotFound
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC 系列:AQS -->学习 Doug Lea 大神思想相关的知识,希望对你有一定的参考价值。
AQS:全称是AbstractQueuedSynchronizer
,一个并发同步管理框架类,是 JUC 的灵魂抽象类。如果要自己去实现一个同步管理框架呢?
个人学习寒食君大佬的解析后觉得可以分为三点:
- 通用性,下层实现透明的同步机制,同时给上层提供业务代码编写的功能
- 利用 CAS 操作,原子的修改共享标志位(由这个标志位来判断共享资源是否空闲)
- 等待队列(埋伏笔:情况①:当共享资源被占用时,直接返回结果、情况②:当共享资源被占用时,让后续的线程进入到等待队列中等待)
与 AQS 的结构有着异曲同工之妙,下面就记录下 AQS 的要素吧(本文只写了独占式的过程,共享式也大差不差)。
AQS 的成员变量属性
这里的state
(注意使用了 volatitle
关键字修饰)为什么不是布尔类型而是整数类型呢?因为这就牵扯到了 AQS 的两种模式 --> 共享模式、独占模式
- 独占模式:当共享资源被一个线程占用时,其他线程无法占用
- 共享模式:当共享资源被一个线程占用时,其他共享模式下的线程能占用
state
为了表示占有资源的线程数量,所以采用的是整数类型。
队列里的节点有两种模式,就是独有和共享:
再来看一下节点 Node 的成员变量:
waitStaus
用来判断线程是否需要挂起(后文有写)。
AQS 的重点就是如何利用标志位state
和这个 FIFO 等待队列来管理多线程的同步状态,AQS 也把这些操作封装成了一些方法tryAcquire
、acquire
(对应着前文的伏笔,tryAcquire
:尝试获取锁,直接返回结果,acquire
:获取锁,进入等待队列,直至获取成功)。
AQS 的核心方法
tryAcquire
该方法被 protected 修改,传入的参数是一个整数,返回一个布尔类型,但方法中只抛出了一个异常。这样做的目的是:让继承的子类必须去重写这个方法,否则就抛出不支持该操作的异常,这种设计就是给了上层调用者开发的空间。
在上层调用了tryAcquire
方法获取到锁后,就去做自己的业务,做完后释放资源;如果获取失败,开发者的这个功能必须要操作这个共享资源呢,那就去调用acquire
方法进入到等待队列。
acquire
该方法由 public final
修饰,表明所有的继承类都可以直接调用这个方法,而且不允许子类去把这个方法重写(很显然,这就是告诉你,调用这个方法是一定能得到锁的)
在 if 判断语句里,你tryAcquire
获取锁失败再去判断&&之后的条件,如果是获取到了锁那就直接结束。接下来看第二个判断条件:acquireQueued(addWaiter()),方法嵌套。
addWaiter
这个方法的作用就是将当前线程封装成一个 node,然后加入等待队列中。源码步骤:
- 创建一个线程节点
- 将该节点放到队尾,如果当前尾节点为空或第一次尝试 CAS 操作失败,则进入完整的入队方法
enq
enq
方法中采用 CAS + 自旋的操作保证插入成功
疑问:为什么不直接在addWaiter
方法中完整入队呢?其实注释中就已经告诉了,先尝试快速入队,不行再完整的入队。
acquireQueued
该方法是对线程进行挂起和响应,以此来实现队列的先进先出。
这两个方法就是当线程使用完共享资源后释放锁的方法。
所以流程总结就是:
如果当前节点是头节点的下一个,那么将会自旋是不断尝试拿锁,直到拿锁成功;否则进行判断是否需要挂起(判断条件:该节点前除了head节点,还有其它节点的,并且waitStaus
为 SIGANL,那么该节点就需要挂起),这样就能保证 head 之后只有一个节点在通过 CAS 来获取锁,就能最大限度的避免无用的自旋来消耗 CPU 资源。
在该节点使用完共享资源后(节点使用完锁后会采用setHead()
方法,变成新的头节点,起一个占位作用),需要释放锁,将自己的waitStaus
置为默认值0,然后程序将会从队列的尾节点向前进行搜索(为什么不从头向后找?因为在setHead()
方法中,已经和队列切断联系了),找到 head 节点后的最近且waitStaus
<= 0的一个节点并唤醒它去争抢这个锁(因为在前面它是被挂起了的)。这样回到了最开始的地方,形成了一个良好的闭环。
以上是关于JUC 系列:AQS -->学习 Doug Lea 大神思想的主要内容,如果未能解决你的问题,请参考以下文章
JUC 系列:AQS -->学习 Doug Lea 大神思想
JUC 系列:AQS -->学习 Doug Lea 大神思想