AbstractQueuedSynchronizer源码分析(ReentrantLock锁的实现)
1. 前言
Java中好多地方用到AbstractQueuedSynchronizer(PS:简称AQS),比如ReentrantLock、线程池,这部分在面试的时候也经常被问到,今天以ReentrantLock为例,通过源码来加深对AQS的理解
2. lock
通常,我们的用法是这样的:
那么lock(),unlock()到底做了什么,我们并不知晓,接下来一步一步揭开她的神秘面纱
2.1. lock
可以看到,ReentrantLock默认是NonfairSync(非公平锁)
2.2. NonfairSync
可以看到,首先判断同步状态是否是0,如果是0则临界资源没有被占用,并且将状态设为1,当前线程获得这个资源,可以访问;否则,调用acquire(1)方法尝试获取资源的访问控制权。
2.3. tryAcquire
尝试再获取一次
如果当前同步状态是0,则跟之前相同,将状态置为1,当前线程获得访问权,返回true
如果当前资源的所有者线程就是当前线程,则状态加1,当前线程仍然获得访问权,返回true
如果以上情况都不是(PS:资源被别的线程占用着),则返回false
2.4. acquireQueued
如果上一步tryAcquire方法返回false,则继续调用acquireQueued方法将线程添加到队列中(PS:链表的尾部)
在添加到链表之前,先封装成Node对象
将当前线程构造成Node对象,节点的模式是排它的,然后将其加到链表的尾部(或是说叫队列),最后将该结点返回
这里有两个特殊的节点:等待队列的头结点 和 等待队列的尾结点
接下来,将刚才构造的节点加到队列中
如果当前节点的前驱节点是头结点(head),并且当前节点再次尝试获取资源(tryAcquire方法),恰好成功了,于是皆大欢喜
如果当前节点的前驱节点既不是head,而且当前节点也没有抢占到资源,则循环直到前驱节点的状态变成SIGNAL,则挂起当前线程
3. unlock
如果资源的所有者线程不是当前线程的话,则抛出异常
如果当前资源同步状态减1恰好是0,则成功释放,同步状态置为0,资源所有者线程置为null,唤醒head的后继节点
4. 小结
加锁
1、默认非公平锁(PS:当前线程不是直接加到等待队列中,而是先尝试获取一次,如果不成功则加到队列中,在加的时候还会尝试一次)
2、临街资源有一个同步状态,0表示当前没有线程占用,则可以直接可以获取到资源(加锁成功)
3、如果资源所有者线程就是当前线程,则状态加1,仍然可以获得锁
3、加锁成功以后,将同步状态置为1,资源所有者线程置为当前线程
4、不成功,则封装成Node加入到等待队列(链表)中,此时,还会像前面一样再尝试(抢占)一次
5、抢占不成功,加到等待队列中,线程挂起
解锁
1、资源所有者线程不是当前线程,则抛异常
2、唤醒下一个结点
AbstractQueuedSynchronizer源码分析(ReentrantLock锁的实现)的更多相关文章
- Java并发系列[2]----AbstractQueuedSynchronizer源码分析之独占模式
在上一篇<Java并发系列[1]----AbstractQueuedSynchronizer源码分析之概要分析>中我们介绍了AbstractQueuedSynchronizer基本的一些概 ...
- AbstractQueuedSynchronizer源码分析
AbstractQueuedSynchronizer源码分析 前提 AQS(java.util.concurrent.locks.AbstractQueuedSynchronizer)是并发编程大师D ...
- Java并发系列[3]----AbstractQueuedSynchronizer源码分析之共享模式
通过上一篇的分析,我们知道了独占模式获取锁有三种方式,分别是不响应线程中断获取,响应线程中断获取,设置超时时间获取.在共享模式下获取锁的方式也是这三种,而且基本上都是大同小异,我们搞清楚了一种就能很快 ...
- Java并发系列[4]----AbstractQueuedSynchronizer源码分析之条件队列
通过前面三篇的分析,我们深入了解了AbstractQueuedSynchronizer的内部结构和一些设计理念,知道了AbstractQueuedSynchronizer内部维护了一个同步状态和两个排 ...
- 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 百篇博客分析OpenHarmony源码 | v27.02
百篇博客系列篇.本篇为: v27.xx 鸿蒙内核源码分析(互斥锁篇) | 比自旋锁丰满的互斥锁 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 自旋锁当立贞 ...
- 鸿蒙内核源码分析(自旋锁篇) | 当立贞节牌坊的好同志 | 百篇博客分析OpenHarmony源码 | v26.02
百篇博客系列篇.本篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 当立贞节牌坊的好同志 | 51.c.h .o 进程通讯相关篇为: v26.xx 鸿蒙内核源码分析(自旋锁篇) | 当立贞节牌坊 ...
- [源码分析]ReentrantLock & AbstractQueuedSynchronizer & Condition
首先声明一点: 我在分析源码的时候, 把jdk源码复制出来进行中文的注释, 有时还进行编译调试什么的, 为了避免和jdk原生的类混淆, 我在类前面加了"My". 比如把Reentr ...
- 【JDK】JDK源码分析-ReentrantLock
概述 在 JDK 1.5 以前,锁的实现只能用 synchronized 关键字:1.5 开始提供了 ReentrantLock,它是 API 层面的锁.先看下 ReentrantLock 的类签名以 ...
- 多线程之美5一 AbstractQueuedSynchronizer源码分析<一>
AQS的源码分析 目录结构 1.什么是CAS ? 2.同步器类结构 3.CLH同步队列 4.AQS中静态内部类Node 5.方法分析 5.1.acquire(int arg ) 5.2.rel ...
- Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析
经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...
随机推荐
- Spark实战
实战 数据导入Hive中全量: 拉链增量:用户.商品表数据量大时用 拉链表动作表 增量城市信息 全量 需求一: 获取点击.下单和支付数量排名前 的品类 ①使用累加器: click_category_i ...
- ImCash:论拥有靠谱数字钱包的重要性!
数字货币被盗已经不是什么新鲜事,前有交易所币安被黑客攻击,Youbit破产,后有“钓鱼邮件“盗号木马,安全对于数字货币用户来讲至关重要. 现行市场痛点: 2017年9月以太坊Parity钱包的漏洞 ...
- babel分析
现在都用 ES6 新语法以及 ES7 新特性来写应用了,但是浏览器和相关的环境还不能友好的支持,需要用到 Babel 转码器来转换成 ES5 的代码 相信大家都看到过如下的名词: babel-pres ...
- VB.NET或C#报错:You must hava a license to use this ActiveX control.
VB.NET或者C# winform开发时,如果使用了Microsoft Visual Basic 6.0 ActiveX,并动态创建该控件实例,那么程序移植到没有安装Visual Basic 6.0 ...
- jdk12+tomcat9 配置
jdk12 没有了jre的配置 直接配置path就可以了 tomcat常规配置,只是启动的时候麻烦一点 需要重新写入jdk jre jvm 到server.bat文件 参考文章: https: ...
- [Educational Round 10][Codeforces 652F. Ants on a Circle]
题目连接:652F - Ants on a Circle 题目大意:\(n\)个蚂蚁在一个大小为\(m\)的圆上,每个蚂蚁有他的初始位置及初始面向,每个单位时间蚂蚁会朝着当前面向移动一个单位长度,在遇 ...
- PHP实现微信模板消息发送给指定用户
使用公众号的模板消息功能,必须是认证过的服务号,需要发送微信号的openid,同一微信号在不同公众号下的openid是不同的,在公众号下是唯一的,获取不到微信号 进入公众平台 功能->模板消息 ...
- SharePoint 更改管理帐户密码步骤
// https://wenku.baidu.com/view/0fffab761ed9ad51f01df2df.html \
- 问题:这个新申请的内存为什么不能free掉?(已解决)
一.问题描述 先上代码, /*** 省略 ***/ uChar *base64 = NULL; /*** 省略 ***/ base64 = (一段内存) /*** 省略 ***/ base64 = s ...
- Java中不定项参数(可变参数)的使用
Java1.5增加了新特性:可变参数:适用于参数个数不确定,类型确定的情况,java把可变参数当做数组处理. 注意事项: 1)不定项参数必须放在参数列表最后一个. 2)不定项参数只能有一个(多 ...



















