图解AQS源码分析(上)

简介: AbstractQueuedSynchronizer抽象的队列式同步器(抽象类)。提供了一个FIFO队列,可以看成是一个用来实现同步锁以及其他涉及到同步功能的核心组件,常见的有:ReentrantLock、CountDownLatch等。

1 简介


AbstractQueuedSynchronizer抽象的队列式同步器(抽象类)。提供了一个FIFO队列,可以看成是一个用来实现同步锁以及其他涉及到同步功能的核心组件,常见的有:ReentrantLock、CountDownLatch等。


其中比较重要的概念有:


state共享资源

FIFO

CAS

park  unpark


2 AQS线程队列


Node是整个队列中最核心的部分,包含CANCELLED、SIGNAL、CONDITION、PROPAGATE四种状态、指向前后节点的指针、thread是节点存储的值。


ReentrantLock中的公平锁与非公平锁都继承了这个抽象类。


20200916104953811.png


ReentrantLock包含公平锁和非公平锁,每种锁里面还包含了抽象的锁Sync,抽象锁执行AQS。


如果当前是线程1拥有锁的话,线程2,3,4会调用park操作来被挂起加入队列中。


当拥有锁的Thread1执行完毕后会调用unpark方法,head指向下一个节点。由于ReentrantLock是一个可重入锁,重入次数被AQS.state记录,每重入一次值 + 1,退出一次 - 1。


3 ReentrantLock实例构建


ReentrantLock默认构造函数创建的是非公平锁,如果想要公平锁的话需要在构造方法中传入true。


20200916105033289.png20200916105033289.png

20200916105033289.png


4 多线程抢锁图示(非公平锁)


线程抢到锁的过程使用CAS实现。

初始时等待队列只有一个Head节点,其中存储的Thread是null,用来占位,线程B,C在队列中使用双向链表的方式与Head相连,调用park挂起。


20200916105236422.png


上图的分步过程见下文。


4.1 A线程加锁


A线程抢锁时通过CAS操作将state改为1,并将AQS的exclusiveOwnerThread属性设为A,表示当前锁的拥有者。


2020091610532027.png


4.2 B线程加锁


此时B线程要进行抢锁,发现state已经是1了,所以CAS操作失败,进入到队列中,waitStatus设置为0

第一次new Node的时候,即创建head,thread设置为了null,waitStatus设置为SIGNAL


20200916105236422.png


4.3 C线程加锁


接着C线程抢锁时,操作同B,会将B的waitStatus设置为SIGNAL,自己的是初始化是的值0


20200916105412111.png


新插入的节点waitStatus值都设为0原因是用来标记队列中最后一个节点,此时不必再进行对后续节点的unpark操作,等待队列中没有节点时会有一个null的节点用作占位,这两个操作都是防止等待队列中没有等待的线程时而变为空。




4.4 A线程解锁


A线程进行解锁操作之后,B线程可以抢到锁,流程如下:


A线程解锁操作:


state设为0

exclusiveOwnerThread设为null表示锁被释放

head节点向后移动一位进行unpark操作唤醒线程B

之前的head节点要被释放


image.png


4.5 B线程解锁


2020091610555516.png


4.6 C线程解锁


20200916105618596.png

相关文章
|
Java 持续交付 数据库
避免服务分层污水池反模式
【6月更文挑战第30天】本文介绍污水池反模式,分层架构在敏捷性、部署性和性能方面得分较低,但具有高测试性和易开发性。关键在于合理分层以降低耦合和提高解耦效果。
607 1
避免服务分层污水池反模式
|
安全 Java
AQS唤醒线程的时候为什么从后向前遍历
AQS唤醒线程的时候为什么从后向前遍历
1283 0
AQS唤醒线程的时候为什么从后向前遍历
|
弹性计算 Linux 网络安全
阿里云ECS云服务器如何开放8080端口?
阿里云服务器ECS处于安全考虑默认自带安全组(仅开放了22号和3389号端口),Tomcat的默认端口号为8080,所以想使用Tomcat不开放8080端口是不行的。很多用户通过修改iptables来开放8080号端口,结果失败,这是由于安全组,对安全组,阿里云亘古不变的安全组开放端口问题。
56948 1
|
存储 数据管理 数据处理
阿里云对象存储OSS收费价格表
2023阿里云对象存储OSS收费价格表,阿里云对象存储OSS包年包月和按量付费,存储包、流量包收费价格,OSS标准(LRS)存储包100GB优惠价33元、500GB存储包半年162元、OSS存储包40GB一年9元,OSS流量包100G 49元/月
6387 0
|
弹性计算 网络协议 应用服务中间件
阿里云服务器开启8080端口图文教程
阿里云服务器8080端口默认是不开启的,默认只开通22和3389端口,阿里云服务器端口是在安全组中配置,端口号来详细说下阿里云服务器8080端口开启教程
阿里云服务器开启8080端口图文教程
|
9天前
|
机器人 API 调度
基于 DMS Dify+Notebook+Airflow 实现 Agent 的一站式开发
本文提出“DMS Dify + Notebook + Airflow”三位一体架构,解决 Dify 在代码执行与定时调度上的局限。通过 Notebook 扩展 Python 环境,Airflow实现任务调度,构建可扩展、可运维的企业级智能 Agent 系统,提升大模型应用的工程化能力。