【Java并发编程实战】----- AQS(一):简介
在前面博客中,LZ讲到了ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch,他们都有各自获取锁的方法,同时相对于Java的内置锁,他们具有明显的优势:花最小的空间开销创建锁、最少的时间开销获得锁、使用更加方便灵活。
参考Java的内置锁,对于JUC同步器而言,他应该具备两个最基本的功能:获取锁,释放锁。其中获取锁应该是先判断当前状态是否可以获取,如果不可以获取则处于阻塞状态,释放应该是释放后修改状态,让其他线程能够得到该锁(唤醒其他线程),如下:
lock:
while(state){ //
getLock(); //获取锁
return currentThread; //返回当前线程
} release:
updateState(); //修改状态
notify other thread; //唤醒其他线程
我们知道,在JUC中,各个同步器获取锁和释放锁的方法都不相同,比如:lock.lock()、Semaphore.acquire()、 CountDownLatch.await()等等,假如他们都各自实现各自的方法,那么这个JUC框架顶多只能算一个中下等的框架设计了。这是AQS腾空出世,AQS作为一个核心的处理框架,他提供了大量的同步操作,同时用户还可以在此类的基础上进行自定义,实现自己的同步器。其主要框架如下:

从上图可以看出AQS是JUC同步器的基石。下面就AQS涉及的技术原理简单阐述下,以后会对其做详细的说明。
1、状态位state
AQS用的是一个32位的整型来表示同步状态的,它是用volatile修饰的:
private volatile int state;
在互斥锁中它表示着线程是否已经获取了锁,0未获取,1已经获取了,大于1表示重入数。同时AQS提供了getState()、setState()、compareAndSetState()方法来获取和修改该值:
protected final int getState() {
return state;
}
protected final void setState(int newState) {
state = newState;
}
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
这些方法需要java.util.concurrent.atomic包的支持,采用CAS操作,保证其原则性和可见性。
2、CLH同步队列
在前面就提到过AQS内部维护着一个FIFO的CLH队列,所以AQS并不支持基于优先级的同步策略。至于为何要选择CLH队列,主要在于CLH锁相对于MSC锁,他更加容易处理cancel和timeout,同时他具备进出队列快、无所、畅通无阻、检查是否有线程在等待也非常容易(head != tail,头尾指针不同)。当然相对于原始的CLH队列锁,ASQ采用的是一种变种的CLH队列锁:
1、原始CLH使用的locked自旋,而AQS的CLH则是在每个node里面使用一个状态字段来控制阻塞,而不是自旋。
2、为了可以处理timeout和cancel操作,每个node维护一个指向前驱的指针。如果一个node的前驱被cancel,这个node可以前向移动使用前驱的状态字段。
3、head结点使用的是傀儡结点。

3、共享锁、互斥锁
在AQS维护的CLH队列锁中,每个节点(Node)代表着一个需要获取锁的线程。该Node中有两个常量SHARE、EXCLUSIVE。其中SHARE代表着共享模式,EXCLUSIVE代表着独占模式。
static final class Node {
/** Marker to indicate a node is waiting in shared mode */
static final Node SHARED = new Node();
/** Marker to indicate a node is waiting in exclusive mode */
static final Node EXCLUSIVE = null;
/////////
}
其中共享模式是允许多个线程可以获取同一个锁,而独占模式则一个锁只能被一个线程持有,其他线程必须要等待。
4、阻塞、唤醒
我们知道在使用Java内置锁时,可以使用wait、notify方法来阻塞、唤醒线程,但是AQS并没有采用该模式,而是通过LockSupport.park() 和 LockSupport.unpark() 的本地方法来实现线程的阻塞和唤醒。
【Java并发编程实战】----- AQS(一):简介的更多相关文章
- 【Java并发编程实战】----- AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...
- 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport
在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...
- 【Java并发编程实战】----- AQS(二):获取锁、释放锁
上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...
- 《Java并发编程实战》读书笔记一 -- 简介
<Java并发编程实战>读书笔记一 -- 简介 并发的历史 并发的历史,也是人类利用有限的资源去提高生产效率的一个的例子. 设想现在有台计算机,这台计算机具有以下的资源: 单核CPU一个 ...
- 【Java并发编程实战】—– AQS(四):CLH同步队列
在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形. 其主要从双方面进行了改造:节点的结构与节点等待机制.在结构上引入了 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantLock之一简介
注:由于要介绍ReentrantLock的东西太多了,免得各位客官看累,所以分三篇博客来阐述.本篇博客介绍ReentrantLock基本内容,后两篇博客从源码级别分别阐述ReentrantLock的l ...
- 【Java并发编程实战】-----“J.U.C”:Semaphore
信号量Semaphore是一个控制访问多个共享资源的计数器,它本质上是一个"共享锁". Java并发提供了两种加锁模式:共享锁和独占锁.前面LZ介绍的ReentrantLock就是 ...
- 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock
ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...
- 《Java并发编程实战》/童云兰译【PDF】下载
<Java并发编程实战>/童云兰译[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062521 内容简介 本书深入浅出地介绍了Jav ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
随机推荐
- jQuery之ajax实现篇
jQuery的ajax方法非常好用,这么好的东西,你想拥有一个属于自己的ajax么?接下来,我们来自己做一个简单的ajax吧. 实现功能 由于jq中的ajax方法是用了内置的deferred模块,是P ...
- 【探索】利用 canvas 实现数据压缩
前言 HTTP 支持 GZip 压缩,可节省不少传输资源.但遗憾的是,只有下载才有,上传并不支持.如果上传也能压缩,那就完美了.特别适合大量文本提交的场合,比如博客园,就是很好的例子. 虽然标准不支持 ...
- C语言 · 4_2找公倍数
问题描述 这里写问题描述. 打印出1-1000所有11和17的公倍数. 样例输入 一个满足题目要求的输入范例.例:无 样例输出 与上面的样例输入对应的输出.例: 代码如下: #include< ...
- java基础_集合List与Set接口
List接口继承了Collection的方法 当然也有自己特有的方法向指定位置添加元素 add(索引,添加的元素); 移除指定索引的元素 remove(索引) 修改指定索引的元素 set ...
- Content Security Policy 入门教程
阮一峰文章:Content Security Policy 入门教程
- Web APi之认证(Authentication)两种实现方式【二】(十三)
前言 上一节我们详细讲解了认证及其基本信息,这一节我们通过两种不同方式来实现认证,并且分析如何合理的利用这两种方式,文中涉及到的基础知识,请参看上一篇文中,就不再叙述废话. 序言 对于所谓的认证说到底 ...
- NDK开发_笔记0
自谷歌搜索退出中国以来,谷歌对全球第二大市场中国的态度一直保持冷淡.可是北京时间12月8日,谷歌2016开发者大会在北京召开,同时专门针对中国的谷歌开发者网站已经上线:https://develope ...
- 利用PowerShell复制SQLServer账户的所有权限
问题 对于DBA或者其他运维人员来说授权一个账户的相同权限给另一个账户是一个很普通的任务.但是随着服务器.数据库.应用.使用人员地增加就变得很枯燥乏味又耗时费力的工作.那么有什么容易的办法来实现这个任 ...
- 虚拟机VMware12.05下安装Ubuntu16.04几个关键地方
在踩了自己按照网上的教程安装Ubuntu之后,仍然踩了不少坑,鼓捣了一段时间,才达到自己想要的界面. 下面就来说说,大家可能也会遇到的情况: 1.安装ISO镜像时候,路径直接选择 你从Ubun ...
- NYOJ 975
这道题一开始本着很朴素的想法就是先输入两头的数据,然后对每组的数据范围下测试中间的数据即可,但是是超时的.原因也很明显,比如计算1~1000的数据之后,假如下一组数据是1~1001,本来只需要多测试下 ...