AQS简简单单过一遍
前言
回顾前面:
只有光头才能变强!
本来我是打算在这章节中写Lock的子类实现的,但看到了AQS的这么一个概念,可以说Lock的子类实现都是基于AQS的。
AQS我在面试题中也见过他的身影,但一直不知道是什么东西。所以本篇我就来讲讲AQS这个玩意吧,至少知道它的概念是什么,对吧~
那么接下来我们就开始吧~
一、AQS是什么?
首先我们来普及一下juc是什么:juc其实就是包的缩写(java.util.concurrnt)
- 不要被人家唬到了,以为juc是什么一个牛逼的东西。其实指的是包而已~
我们可以发现lock包下有三个抽象的类:
- AbstractOwnableSynchronizer
- AbstractQueuedLongSynchronizer
- AbstractQueuedSynchronizer
通常地:AbstractQueuedSynchronizer简称为AQS
我们Lock之类的两个常见的锁都是基于它来实现的:
那么我们来看看AbstractQueuedSynchronizer到底是什么,看一个类是干什么的最快途径就是看它的顶部注释
通读了一遍,可以总结出以下比较关键的信息:
- AQS其实就是一个可以给我们实现锁的框架
- 内部实现的关键是:先进先出的队列、state状态
- 定义了内部类ConditionObject
- 拥有两种线程模式
- 独占模式
- 共享模式
- 在LOCK包中的相关锁(常用的有ReentrantLock、 ReadWriteLock)都是基于AQS来构建
- 一般我们叫AQS为同步器
二、简单看看AQS
上面也提到了AQS里边最重要的是状态和队列,我们接下来就看看其源码是怎么样的...
2.1同步状态
使用volatile修饰实现线程可见性:
修改state状态值时使用CAS算法来实现:
2.2先进先出队列
这个队列被称为:CLH队列(三个名字组成),是一个双向队列
看看它队列源码的组成:
static final class Node {
// 共享
static final Node SHARED = new Node();
// 独占
static final Node EXCLUSIVE = null;
// 线程被取消了
static final int CANCELLED = 1;
// 后继线程需要唤醒
static final int SIGNAL = -1;
// 等待condition唤醒
static final int CONDITION = -2;
// 共享式同步状态获取将会无条件地传播下去(没看懂)
static final int PROPAGATE = -3;
// 初始为0,状态是上面的几种
volatile int waitStatus;
// 前置节点
volatile Node prev;
// 后继节点
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { // Used by addWaiter
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // Used by Condition
this.waitStatus = waitStatus;
this.thread = thread;
}
}
2.3acquire方法
获取独占锁的过程就是在acquire定义的,该方法用到了模板设计模式,由子类实现的~
过程:acquire(int)尝试获取资源,如果获取失败,将线程插入等待队列。插入等待队列后,acquire(int)并没有放弃获取资源,而是根据前置节点状态状态判断是否应该继续获取资源,如果前置节点是头结点,继续尝试获取资源,如果前置节点是SIGNAL状态,就中断当前线程,否则继续尝试获取资源。直到当前线程被park()或者获取到资源,acquire(int)结束。
来源:
2.4release方法
释放独占锁的过程就是在acquire定义的,该方法也用到了模板设计模式,由子类实现的~
过程:首先调用子类的tryRelease()方法释放锁,然后唤醒后继节点,在唤醒的过程中,需要判断后继节点是否满足情况,如果后继节点不为且不是作废状态,则唤醒这个后继节点,否则从tail节点向前寻找合适的节点,如果找到,则唤醒.
来源:
三、最后
总结一下AQS到底是什么吧:
- juc包中很多可阻塞的类都是基于AQS构建的
- AQS可以说是一个给予实现同步锁、同步器的一个框架,很多实现类都在它的的基础上构建的
- 在AQS中实现了对等待队列的默认实现,子类只要重写部分的代码即可实现(大量用到了模板代码)
有兴趣的同学可去看源码和下面的链接继续学习,我这里就不讲述了。简简单单把AQS过一遍~
明天就看Lock显式锁实现咯~~~
参考资料:
- https://blog.csdn.net/panweiwei1994/article/details/78769703
- https://zhuanlan.zhihu.com/p/27134110
- http://cmsblogs.com/?page_id=111
如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y。为了大家方便,刚新建了一下qq群:742919422,大家也可以去交流交流。谢谢支持了!希望能多介绍给其他有需要的朋友
文章的目录导航:
AQS简简单单过一遍的更多相关文章
- Lock锁子类了解一下
前言 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 多线程基础必要知识点!看了学习多线程事半功倍 Java锁机制了解一下 AQS简简单单过一遍 只有光头才能变强! 上一篇已经将Loc ...
- Object对象你真理解了吗?
前言 五一回家又断更了一个放假时间了~~~ 只有光头才能变强 回顾前面: ThreadLocal就是这么简单 多线程三分钟就可以入个门了! 多线程基础必要知识点!看了学习多线程事半功倍 Java锁机制 ...
- 【Java】几道让你拿offer的知识点
前言 只有光头才能变强 之前在刷博客的时候,发现一些写得比较好的博客都会默默收藏起来.最近在查阅补漏,有的知识点比较重要的,但是在之前的博客中还没有写到,于是趁着闲整理一下. 文本的知识点: Inte ...
- java 备用待迁移
Java基础 2018年如何快速学Java 泛型就这么简单 注解就这么简单 Druid数据库连接池就是这么简单 Object对象你真理解了吗? JDK10都发布了,nio你了解多少? COW奶牛!Co ...
- 并发编程(三):从AQS到CountDownLatch与ReentrantLock
一.目录 1.AQS简要分析 2.谈CountDownLatch 3.谈ReentrantLock 4.谈消费者与生产者模式(notfiyAll/wait.si ...
- 深入浅出AQS之独占锁模式
每一个Java工程师应该都或多或少了解过AQS,我自己也是前前后后,反反复复研究了很久,看了忘,忘了再看,每次都有不一样的体会.这次趁着写博客,打算重新拿出来系统的研究下它的源码,总结成文章,便于以后 ...
- 并发编程(十):AQS
AQS全称为AbstractQueuedSynchronizer,是并发容器中的同步器,AQS是J.U.C的核心,它是抽象的队列式的同步器,AQS定义了一套多线程访问共享资源的同步器框架,许多同步类都 ...
- Java并发编程之AQS
一.什么是AQS AQS(AbstractQueuedSynchronize:队列同步器)是用来构建锁或者其他同步组件的基础框架,很多同步类都是在它的基础上实现的,比如常用的ReentrantLock ...
- 走进 AQS 瞧一瞧看一看
并发中有一块很重要的东西就是AQS.接下来一周的目标就是它. 看复杂源码时,一眼望过去,这是什么?不要慌,像剥洋葱一样,一层层剥开(哥,喜欢"扒开"这个词). 参考资源: http ...
随机推荐
- 1290 - The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
解决问题:windows下:修改my.ini 在[mysqld]内加入secure_file_priv = linux下:修改my.cnf 在[mysqld]内加入secure_file_priv = ...
- 爬虫模块BeautifulSoup
中文文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html# 1.1 安装BeautifulSoup模块 ...
- sublimeText3 中配置sass环境,并将编译后文件保存到指定文件夹
sass基于ruby引擎,所以安装时ass.compass之前需要安装ruby.具体的链接应该是(http://rubyinstaller.org/downloads).下载并安装相应的版本,勾选第二 ...
- hadoop原理
MapReduce工作原理图文详解 前言: 前段时间我们云计算团队一起学习了hadoop相关的知识,大家都积极地做了.学了很多东西,收获颇丰.可是开学后,大家都忙各自的事情,云计算方面的动静都不太 ...
- RxJava系列番外篇:一个RxJava解决复杂业务逻辑的案例
之前写过一系列RxJava的文章,也承诺过会尽快有RxJava2的介绍.无奈实际项目中还未真正的使用RxJava2,不敢妄动笔墨.所以这次还是给大家分享一个使用RxJava1解决问题的案例,希望对大家 ...
- python 迭代器 生成器
迭代器 生成器 一 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前 ...
- POJ-2570 Fiber Network---Floyd+二进制表示集合
题目链接: https://vjudge.net/problem/POJ-2570 题目大意: 一些公司决定搭建一个更快的网络,称为"光纤网".他们已经在全世界建立了许多站点,这 ...
- jacascript 事件对象event
前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! 在触发DOM上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的信息.所有浏览 ...
- 关于字数太多直接变成省略号的方法css
文字超出限制的宽度自动隐藏,并且变为省略号 这是之前写的,现在要做一个两行的 于是万能找百度,居然真的有这个方法: 于是,我就变成了搬运工:○( ^皿^)っHiahiahia- http://blog ...
- [LeetCode] Split Array into Consecutive Subsequences 将数组分割成连续子序列
You are given an integer array sorted in ascending order (may contain duplicates), you need to split ...