一、AQS是什么

AQS的完整类名是——AbstractQueuedSynchronizer(直译过来就是抽象队列同步器)。从字面上就能看出来,是专门用于实现同步功能的一个抽象框架。事实上,AQS是著名的JDK并发包设计者Doug Lea定义的一套用于控制多线程并发访问共享资源的基础框架,许多并发包工具实现都依赖于它,如常用的ReentrantLock、ReadWriteLock、Semaphore、CountDownLatch和ThreadPoolExecutor 的 Worker

二、为什么要使用AQS

设想一下,如果没有AQS,要实现一个锁需要如何进行?

如果没有 AQS,那么就需要开发者自己去实现以下内容,至少包括:

  • 同步状态的原子性管理(比如锁状态的获取和释放)
  • 线程的阻塞与唤醒
  • 阻塞队列的管理

举个例子:实现一个类似ReentrantLock功能的可重入锁 ,需要一个变量维护锁被重入的次数,同时必须保证多线程同时操作该变量时是线程安全的;同时竞争锁失败的线程,可能需要让它们陷入阻塞并进行排队,同时要在合适的时机将其唤醒。
其实不只是对于锁而言,其他的进行多线程并发控制的同步组件基本都需要上述这些操作。这一系列的操作流程都是繁杂而重复的,此时AQS的意义就凸显出来了。

AQS定义好了这一套骨架流程的操作,不同的同步组件只需要继承AQS并重写指定的方法,就可以实现同步组件自身的
功能逻辑。这其实就是模板方法的思想

总结一下,就是:同步组件是面向普通开发者的,AQS是面向同步组件开发者的

三、AQS 的设计原理

AQS的实现源码有2000多行代码,相对还是比较复杂的。但是我们将其实现细节抛开,其实重点就围绕着以下三大部分:

  • state 状态
  • CLH队列
  • 获取/释放

3.1 state 状态

如果我们的 AQS 想要去管理或者想作为协作工具类的一个基础框架,那么它必然要管理一些状态,而这个状态在 AQS 内部就是用 state 变量去表示的。它的定义如下:

    /*** The synchronization state.*/private volatile int state;

而 state可以根据具体组件类的作用不同而表示不同的含义,比如:

  • 信号量Semaphore:state 表示剩余许可的数量。比如我们把 state 初始化设置为 5,表示许可证初始一共有5个,然后当某个线程取走1个许可证之后,这个 state 就会变为4,所以信号量的 state 相当于是一个内部计数器。
  • CountDownLatch :state 表示是需要“倒数”的数量。一开始我们假设把它设置为 5,当每次调用 CountDown 方法时,state 就会减 1,一直减到 0 的时候就代表这个门闩被放开。
  • ReentrantLock :表示的是锁的占有情况。初始化时是 0,表示没有线程占有锁;如果 state 变成了 1,则代表这个锁已经被某个线程所持有了。
  • ReadWriteLock:高16位表示读锁状态,低16位表示写锁状态。

下面看AQS提供的state状态的获取和变更操作:

  /*** Returns the current value of synchronization state.* This operation has memory semantics of a {@code volatile} read.* @return current state value*/protected final int getState() {return state;}/*** Sets the value of synchronization state.* This operation has memory semantics of a {@code volatile} write.* @param newState the new state value*/protected final void setState(int newState) {state = newState;}/*** Atomically sets synchronization state to the given updated* value if the current state value equals the expected value.* This operation has memory semantics of a {@code volatile} read* and write.** @param expect the expected value* @param update the new value* @return {@code true} if successful. False return indicates that the actual*         value was not equal to the expected value.*/protected final boolean compareAndSetState(int expect, int update) {// See below for intrinsics setup to support thisreturn unsafe.compareAndSwapInt(this, stateOffset, expect, update);}

1.getState读取——由于state变量带有volatile关键字进行修饰,能保证内存可见性,getState方法获取就能直接最新的值。
2.setState直接写入——直接对state = newState;赋值操作,此操作一般是用于同步组件在独占之后的状态变更设置,无进行额外同步。
3.compareAndSetState(int expect, int update) CAS操作写入,借助Unsafe工具类的 CAS 操作,利用 CPU 指令的原子性保证了这个操作的原子性。

3.2 CLH队列 (FIFO)

CLH队列作用是存储竞争失败从而进入阻塞等待状态的线程。
队列内部是双向链表的结构,分别用 head 和 tail 来表示头尾节点, 初始化的时候两个节点都指向了一个空节点。
头节点当做当前持有锁的线程,尾节点则是每个新的阻塞线程进来队列时要插入的位置,插入尾节点需要通过CAS进行插入操作原子性控制。

(图文引用自AQS英文文档)

3.3 同步状态的获取和释放

AQS定义了独占式获取与释放同步状态和共享式获取与释放同步状态4中操作类型,需要子类自己实现。

四、小结

本文介绍了什么AQS框架出现的背景作用以及AQS核心的设计原理。 AQS是面向同步组件开发者的基础框架,使用模板方法设计模式的思想,将同步状态的管理 、 阻塞队列和线程的阻塞唤醒等处理流程定义成固定的模板。组件开发者无需关注底层细节,只需要重写少数几个相关方法即可。

参考资料:AQS官方文档

一文轻松看透AQS的核心设计思想相关推荐

  1. OLTP 系统和 OLAP 系统的核心设计思想

    关于 OLTP 系统和 OLAP 系统的核心设计思想 数据存储系统的关于查询的典型操作: -- 第一种需求: 根据 key(1) 找 value(name,age), 单点查询 select name ...

  2. Shiro————核心设计思想

    引言 以此篇博客为引,开启一个新的专栏分类--Shiro. 之前在工作中有比较快速的学习过Shiro安全框架,但经过一年的荒废,已经不是很熟悉了,通过这个系列,深入研究和学习Shiro的一些知识,填补 ...

  3. 通用权限实现的核心设计思想

    1). 操作权限:什么资源,有什么权限?   1.用户有什么权限?   2.角色有什么权限?   3.有什么权限可以访问哪个模块? 2). 数据权限 什么对象->对->什么资源有什么权限? ...

  4. linux/unix核心设计思想

    1) 程序应该小而专一,程序应该尽量的小,且只专注于一件事上,不要开发那些看起来有用但是90%的情况都用不到的特性: 2) 程序不只要考虑性能, 程序的可移植性更重要,shell和perl,pytho ...

  5. java ee核心设计思想,JavaEE核心设计思想是什么 (5.0分)

    最大诚信原则中弃权与禁止反言的规定主要对()的约束. 以下哪个白内障期可能发生青光眼( ) 3 . Many people believe, however, that our progress de ...

  6. 【个人整理】一文看尽目标检测算法SSD的核心架构与设计思想

    前言:SSD(Single Shot MultiBox Detector)是大神Wei Liu在 ECCV 2016上发表的一种的目标检测算法.对于输入图像大小300x300的版本在VOC2007数据 ...

  7. DDD的创新思想:开发即设计思想

    领域驱动设计(DDD)和微服务架构(MSA)近年来非常火热,尤其是在互联网公司的生产实践过程中.微服务架构为互联网公司自身业务的发展壮大提供了技术支撑,日渐显现出解决复杂业务需求的威力.更多的IT公司 ...

  8. 彻底理解OkHttp - OkHttp 源码解析及OkHttp的设计思想

    OkHttp 现在统治了Android的网络请求领域,最常用的框架是:Retrofit+okhttp.OkHttp的实现原理和设计思想是必须要了解的,读懂和理解流行的框架也是程序员进阶的必经之路,代码 ...

  9. OSGI框架的功能和设计思想

    摘录自InfoQ电子书:<OSGi原理与最佳实践(精选版).pdf> 支持模块化的动态部署 基于 OSGi 而构建的系统可以以模块化的方式(例如 jar 文件等)动态地部署至框架中,从而增 ...

最新文章

  1. 红帽RHEL6.8离线环境下升级到RHEL7.3
  2. 测试一个config server 服务器挂机后,集群是否能读写数据
  3. R语言与正态总体均值的区间估计
  4. jqgrid 编辑列拿不到值_德云社十大杰出学霸,岳云鹏赫然在列,小岳岳你这是否有点牵强...
  5. C++编程连接string字符串和int数字的好方法
  6. 韩顺平php教程笔记,PHP笔记,韩顺平php笔记_PHP教程
  7. 0x29——如何把自己iphone app传到iphone上
  8. 李明顺专栏周5月12日:给门户支招
  9. 安卓10侧边返回_Flyme 8 体验:可能是最好的国产安卓系统
  10. Google将Material Design带到CSS、HTML与JavaScript上
  11. 一张图学会python3语法-一张图片在Python操作下的4种玩法(附源码)
  12. USB协议 - UVC标准协议规范(二)
  13. 智象运维干货 | HP iLo4 Smash CLP命令行参考
  14. 05 mapABC示例 leo
  15. Linux设置小红点键盘,debian linux上安装thinkpad小红点驱动/Installing Debian On Thinkpad – Trackpoint...
  16. DC/DC浪涌电流简记
  17. jekenis实现oracle导入导出,What would the author do with Ken Smit..._考试资料网
  18. 浅析贝叶斯神经网络(Based on Variational Bayesian)
  19. Arduino连接pH计
  20. python整体向右缩进两个级别_关于python:IndentationError:unindent与任何外部缩进级别都不匹配...

热门文章

  1. 计算机学硕考数二的一本学校,软件工程专硕和学硕,专硕是考数二,学硕考数一吗...
  2. 单片机 fir数字滤波c语言,单片机实时处理的简单FIR滤波器设计 - 控制/MCU - 电子发烧友网...
  3. 幼儿园微课怎么制作?怎么给微课配音?
  4. 开启灯光就是近光吗_汉兰达自动大灯怎么用,自动大灯AUTO时是近光还是远光 - 闹太套汽车之家...
  5. 如何设计mysql的表结构_数据库的数据表的结构是如何设计的?
  6. 数据仓库设计与开发-1-分层设计
  7. 设计模式领域公认的3本经典著作之一《设计模式之禅》 [豆瓣评分 8.70]
  8. CSS Houdini
  9. 京东白条的本质,是信用卡还是信用贷款?可以当作贷款来用吗?
  10. Excel快速将自己的名字识别为二维码