Java并发框架——什么是AQS框架
什么是AQS框架
1995年sun公司发布了第一个java语言版本,可以说从jdk1.1到jdk1.4期间java的使用主要是在移动应用和中小型企业应用中,在此类领域中基本不用设计大型并发场景,当然也没有大型互联网公司使用java,因为担心它本身的性能。在互联网及服务器硬件迅猛的发展下,sun公司更加注重企业级应用方面,毫无疑问高并发是一个重要的主题,于是在J2SE5.0(jdk1.5)代号为老虎的版本中增加了更加强大的并发相关的操作包——java.util.concurrent。此后java在高并发中表现优异,很多大型互联网公司都使用java作为主要开发语言,例如阿里巴巴、ebay等,这些公司系统的访问绝对是属于世界级的大型并发场景,反映了java在大型并发场景是可行的。Jdk的并发包提供了各种锁及同步机制,其实现的核心类是AbstractQueuedSynchronizer,我们简称为AQS框架,它为不同场景提供了实现锁及同步机制的基本框架,为同步状态的原子性管理、线程的阻塞、线程的解除阻塞及排队管理提供了一种通用的机制。
Jdk的并发包(juc)的作者是Doug Lea,但其中思想却是结合了多位大师的智慧,如果你想深入理解juc的相关理论可以参考Doug
Lea写的《The_java.util.concurrent_Synchronizer_Framework》论文。从这里可以找到AQS的理论基础,包括框架的基本原理、需求、设计、实现思路、用法及性能,由于这些方面篇幅较大,本文不打算涉及所有方面,主要将针对AQS类的结构及相关操作进行分析。
ASQ将线程封装到一个Node里面,并维护一个CHL Node FIFO队列,它是一个非阻塞的FIFO队列,也就是说在并发条件下往此队列做插入或移除操作不会阻塞,是通过自旋锁和CAS保证节点插入和移除的原子性,实现无锁快速插入。
其实AbstractQueuedSynchronizer主要就是维护了一个state属性、一个FIFO队列和线程的阻塞与解除阻塞操作。state表示同步状态,它的类型为32位整型,对state的更新必须要保证原子性。这里的队列是一个双向链表,每个节点里面都有一个prev和next,它们分别是前一个节点和后一个节点的引用。需要注意的是此双向链表除了链头其他每个节点内部都包含一个线程,而链头可以理解为一个空节点。
图2-5-5-1
对于队列的结构我们需要深入理解下,图2-5-5-2展示的是组成双向链表其中一个节点的结构,该节点包含五个主要元素,表示的意思如下表,
图2-5-5-2
|
属性 |
含义 |
|
Node prev |
前驱节点,指向前一个节点 |
|
Node next |
后续节点,指向后一个节点 |
|
Node nextWaiter |
用于存储condition队列的后续节点 |
|
Thread thread |
入队列时的当前线程 |
|
int waitStatus |
有五种状态: ① SIGNAL,值为-1,表示当前节点的后续节点中的线程通过park被阻塞了,当前节点在释放或取消时要通过unpark解除它的阻塞。 ② CANCELLED,值为1,表示当前节点的线程因为超时或中断被取消了。 ③ CONDITION,值为-2,表示当前节点在condition队列中。 ④ PROPAGATE,值为-3,共享模式的头结点可能处于此状态,表示无条件往下传播,引入此状态是为了优化锁竞争,使队列中线程有序地一个一个唤醒。 ⑤ 0,除了以上四种状态的第五种状态,一般是节点初始状态。 |
前驱节点prev的引入主要是为了完成超时及取消语义,前驱节点取消后只需向前找到一个未取消的前驱节点即可;后续节点的引入主要是为了优化后续节点的查找,避免每次从尾部向前查找;nextWaiter用于表示condition队列的后续节点,此时prev和next属性将不再使用,而且节点状态处于Node.CONDITION;
waitStatus表示的是后续节点状态,这是因为AQS中使用CLH队列实现线程的结构管理,而CLH结构正是用前一节点某一属性表示当前节点的状态,这样更容易实现取消和超时功能。
上面是对节点及节点组成队列的结构的介绍,接着介绍AQS相关的一些操作,包括锁的获取与释放、队列的管理、同步状态的更新、线程阻塞与唤醒、取消中断与超时中断等等。
喜欢研究java的同学可以交个朋友,下面是本人的微信号:
Java并发框架——什么是AQS框架的更多相关文章
- 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport
在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...
- java并发包分析之———AQS框架
一.什么是同步器 多线程并发的执行,之间通过某种 共享 状态来同步,只有当状态满足 xxxx 条件,才能触发线程执行 xxxx . 这个共同的语义可以称之为同步器.可以认为以上所有的锁机制都可以基 ...
- 【Java并发编程实战】----- AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...
- Java并发编程总结3——AQS、ReentrantLock、ReentrantReadWriteLock(转)
本文内容主要总结自<Java并发编程的艺术>第5章——Java中的锁. 一.AQS AbstractQueuedSynchronizer(简称AQS),队列同步器,是用来构建锁或者其他同步 ...
- Java并发编程-看懂AQS的前世今生
在具备了volatile.CAS和模板方法设计模式的知识之后,我们可以来深入学习下AbstractQueuedSynchronizer(AQS),本文主要想从AQS的产生背景.设计和结构.源代码实现及 ...
- Java并发编程总结3——AQS、ReentrantLock、ReentrantReadWriteLock
本文内容主要总结自<Java并发编程的艺术>第5章——Java中的锁. 一.AQS AbstractQueuedSynchronizer(简称AQS),队列同步器,是用来构建锁或者其他同步 ...
- Java并发编程:用AQS写一把可重入锁
Java并发编程:自己动手写一把可重入锁详述了如何用synchronized同步的方式来实现一把可重入锁,今天我们来效仿ReentrantLock类用AQS来改写一下这把锁.要想使用AQS为我们服务, ...
- 【Java并发编程实战】—– AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...
- JAVA并发编程: CAS和AQS
版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/u010862794/article/details/72892300 说起JAVA并发编程,就不得不聊 ...
随机推荐
- 医疗器械c#上位机开发指引教程
此教程面向的读者:对医疗器械上位机编程有兴趣,或者急需了解医疗器械(尿常规.血液分析.生化.心电.B超等医疗下位仪器)的编程流程.编程细节的程序员. 1.得到仪器协议 当我们需要与医疗器械等下位机数据 ...
- [NOI 2010]能量采集
Description 题库链接 给你一个 \(n\times m\) 的坐标轴.对于坐标轴的每一个正整数整点 \((x,y)\) 其对答案产生的贡献为 \(2k+1\) ,其中 \(k\) 表示这个 ...
- StopAllSounds
10月3日,在杭州市西湖景区,一只小松鼠不停地接受一道道食物,花生.玉米.饼干,可谓来者不拒,憨态可掬的模样吸引了众多围观者...Description 小松鼠开心地在树之间跳跃着,突然她停了下来 ...
- ●BZOJ 4310 跳蚤
●赘述题目 给出一个字符串,要求分成k个子串,然后求出每个子串的字典序最大的子串(我称它为子子串),要使这k个子子串中的字典序最大的那个串(即魔力串)最小.输出该魔力串. (本题个人感觉很好,比较综合 ...
- bzoj 3174: [Tjoi2013]拯救小矮人
Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀上,知道最顶端的小矮人伸直胳膊可以碰到陷阱口.对于每一个小矮人, ...
- [Noi2015]荷马史诗
来自FallDream的博客,未经允许,请勿转载,谢谢. 追逐影子的人,自己就是影子. ——荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的 ...
- bzoj3048[Usaco2013 Jan]Cow Lineup 尺取法
3048: [Usaco2013 Jan]Cow Lineup Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 225 Solved: 159[Subm ...
- Gradle学习之部署上传项目
原先在公司做项目时,写了一个简单的基于gradle部署项目的脚本,今天翻出来记录一下 一.build.gradle buildscript { ext { env = System.getProper ...
- Python virtualenv 使用总结篇
一.virtualenv的安装 1.使用pip全局安装virtualenv,建议使用pip 1.3或更高版本,在1.3之前,pip没有通过SSL从PYPI下载. $ [sudo] pip instal ...
- 笔记11 在XML中声明切面(2)
为通知传递参数 1.声明一个CompactDiscs接口.内部包含两个方法: show() 用于显示唱片的名字和艺术风格 playTrack(int number) 根据传入的磁道数播放相应磁道的音乐 ...