10.1 如何学习AQS

10.1.1学习AQS的思路

  • 学习AQS的目的主要是想理解原理、提高技术,以及应对面试
  • 先从应用层面理解为什么需要他如何使用它,然后再看一看我们Java代码的设计者是如何使用它的了解它的应用场景

这样之后我们再去分析它的结构,这样的话我们就学习得更加轻松了

10.1.2 为什么需要AQS

  • 锁和协作类有共同点:闸门
  • 我们已经学过了ReentrantLock和Semaphore ,有没有发现它们有共同点?很相似?
  • 事实上,不仅是ReentrantLock和Semaphore ,包括CountDownLatch、ReentrantReadWriteLock都有这样类似的”协作”(或者叫“同步”)功能,其实,它们底层都用了一个共同的基类,这就是AQS

  • 因为上面的那些协作类,它们有很多工作都是类似的,所以如果能提取出一个工具类,那么就可以直接用,对于ReentrantLock和Semaphore而言就可以屏蔽很多细节,只关注它们自己的“业务逻辑”就可以了

10.2 Semaphore和AQS的关系

Semaphore内部有一个Sync类,Sync继承了AQS,CountDownLatch也是一样的。

image.png
Semaphore内部有一个Sync对象。
image.png

Sync继承了AQS,ReentrantLock也是一样的。
image.png

10.3 比喻:HR和AQS的职责统一

比喻:群面、单面
image.png

相同点:

  • 安排就坐、叫号、先来后到等HR的工作就是AQS做的工作。
  • 面试官利用AQS,面试官就是类似于AQS
  • 去管面试者需要一个地方坐着休息 ,这些都交给HR去做

具体到工具类

  • Semaphore : 一个人面试完了以后,后一个人才能进来继续面试
  • CountDownLatch : 群面,等待10人到齐
  • Semaphore、CountDownLatch这些同步 工具类,要做的,就只是写下自己的“要人”规则。比如是”出一一个,进一个”或者说”凑齐10人,一起面试”
  • 剩下的招呼面试者的脏活累活交给AQS来做

如果没有AQS

  • 就需要每个协作工具自己实现:
  • 同步状态的原子性管理
  • 线程的阻塞与解除阻塞
  • 队列的管理

在并发场景下,自己正确且高效实现这些内容,是相当有难度的,所以我们用AQS来帮我们把这些脏活累活都搞定,我们只关注业务逻辑就够了

AQS的作用

  • AQS是一个用于构建锁、同步器、协作工具类的工具类(框架)。有了AQS以后,更多的协作工具类都可以很方便得被写出来
  • 一句话总结:有了AQS ,构建线程协作类就容易多了。

AQS的重要性、地位

  • AbstractQueuedSynchronizer是Doug Lea写的,从JDK1.5加入的一个基于FIFO等待队列实现的一个用于实现同步器的基础框架,我们用IDE看AQS的实现类,可以发现实现类有以下这些:

使用到AQS的地方
image.png

10.4 AQS的三要素

AQS内部原理解析

  • AQS最核心的就是三大部分:
  • state
  • 控制线程抢锁和配合的FIFO队列
  • 期望协作工具类去实现的获取/释放等重要方法

state状态

  • 这里的state的具体含义,会根据具体实现类的不同而不同,比如在Semaphore里,它表示”剩余的许可证的数量”, 而在CountDownLatch里,它表示“还需要倒数的数量’
  • state是volatile修饰的,会被并发地修改,所以所有修改state的方法都需要保证线程安全,比如getState、setState以及compareAndSetState操作来读取和更新这个状态。这些方法都依赖于j.u.c.atomic包的支持

state状态

  • 在ReentrantLock中
  • state用来表示”锁”的占有情况,包括可重入计数
  • 当state的值为0的时候,标识改Lock不被任何线程所占有

image.png
image.png

image.png

image.png

image.png

image.png
image.png
需要每个类自己去实现。
image.png

10.5 AQS简要分析

image.png

image.pngimage.png

image.pngimage.png

image.png

image.png

image.png

release
image.png
唤醒所有线程。
image.png

image.png

10.6 许可证的颁发

semaphore实现相对简单。
image.png

image.png

image.png

10.7 AQS在ReentrantLock

image.png

image.png

image.png

image.png

image.png

10.8 DIY一次性门闩

image.png10.9 AQS核心思路

10.10 AQS补充材料(选修)

以下文章是关于AQS源码分析的,通常并不要求掌握,我找了一些优质学习资源,提供给小伙伴参考:
美团技术团队《从ReentrantLock的实现看AQS的原理及应用》:https://mp.weixin.qq.com/s/sA01gxC4EbgypCsQt5pVog
老钱《打通 Java 任督二脉 —— 并发数据结构的基石》:https://juejin.im/post/5c11d6376fb9a049e82b6253
HongJie《一行一行源码分析清楚AbstractQueuedSynchronizer》:https://javadoop.com/post/AbstractQueuedSynchronizer
爱吃鱼的KK《AbstractQueuedSynchronizer 源码分析 (基于Java 8)》:https://www.jianshu.com/p/e7659436538b
waterystone《Java并发之AQS详解》:https://www.cnblogs.com/waterystone/p/4920797.html
英文论文的中文翻译:https://www.cnblogs.com/dennyzhangdd/p/7218510.html
AQS作者的英文论文:http://gee.cs.oswego.edu/dl/papers/aqs.pdf