AQS源码解析

今天清明节放假正好趁此总结一下AQS的源码分析😊😊😊

AbstractQueuedSynchronizer 的简称,Doug Lea大师编写的AQS源码,其实就是对CAS的封装和丰富,用于实现同步器(如锁和信号量等)的基础框架

其实就是一个通用的同步框架,设置这样一个框架要满足以下几点:

  • 通用性:在实现底层必要的同步机制后,给上层调用留有空间,也就是保持对外接口的简单性和纯粹性
  • 利用CAS,原子的修改共享标志位
  • 等待队列:让队列的头部进行自旋获取标志位,而其他的线程则挂起

AQS的一个成员变量state,就是来判断共享资源是否被占用的标志位,设置为int类型是为了记录重入的次数,还有就是共享模式下表示线程的数量

然后它还有一个表示队列头尾的head、tail指针,这两个指针维护了一个FIFO的双向链表来对线程进行管理

java 复制代码
 1 private transient volatile Node head;
 2 private transient volatile Node tail;

队列中的每一个节点Node其实就是对线程的封装,其中也包括四种线程在队列中的等待状态,然后Node中方法也很简单,其中有一个就是获取前置Node

队列中的节点有两种模式,共享和独占,我说一下独占把,ReentrantLock底层就是基于独占模式的AQS来实现的

我们设计这样一个框架其实有两种主要的使用场景:

  • 尝试获得锁,不管有没有获得立即返回
  • 必须获得锁,如果当前锁被占用,则进行等待

源码中的tyrAcquire和acquire正好对应了这两种场景:

tyrAcquire在AQS中是直接抛出异常,是为了让使用的上层自己实现,因为在尝试获得锁的过程中可能包含业务自定义的逻辑,比如是否可重入

acquire方法是重要的,acquireQueued(addWaiter(Node.EXCLUSIVE),arg)

addWaiter(Node.EXCLUSIVE),arg方法是将当前线程封装为一个Node,然后加入等待队列,因为是符合FIFO的,所以通过CAS操作将Node添加到队尾

这里它采用了快速插入的机制,就是一开始先假设并发量比较少(就是前置节点不为空)的情况下CAS进行插入,如果插入失败,则执行enq(node);方法来循环尝试插入

在队列中插入成功后返回一个Node,接下来就是acquireQueued方法

它首先去拿当前节点的前置节点,如果前置节点为head,说明是队首然后当前节点有权限来尝试获得锁,如果不是队首,然后看当前线程是否需要挂起等待,如果需要就挂起等待,如果不需要则继续循环判断是否有权限来尝试获得锁

当前线程是否需要挂起等待的逻辑:

它判断它的前置节点是否也在等待获得锁,如果是,则当前这个线程就挂起等待,如果当前线程是取消状态,则从队列中取消该节点

如果判断当前节点需要被挂起,则执行下面方法:

就是将当前线程挂起阻塞在这,一直等到持有锁的线程来调用relese方法来唤醒

大量线程挂起,然后得有relese释放,来看一下relese的释放:

和tryAcquire一样,它的tryRelese也是交给上层去实现

主要是relese方法,来看unparkSuccessor方法是怎么释放的:

它是从队尾依次向前搜索,找到head后面最靠前的并且是非CANCELED的节点来唤醒,调用unpark

从后往前搜索是为了避免在多线程下新建Node节点时没有与后面节点建立Next连接导致搜索中断

相关推荐
重庆小透明30 分钟前
力扣刷题记录【1】146.LRU缓存
java·后端·学习·算法·leetcode·缓存
博观而约取1 小时前
Django 数据迁移全解析:makemigrations & migrate 常见错误与解决方案
后端·python·django
寻月隐君2 小时前
Rust 异步编程实践:从 Tokio 基础到阻塞任务处理模式
后端·rust·github
GO兔2 小时前
开篇:GORM入门——Go语言的ORM王者
开发语言·后端·golang·go
Sincerelyplz2 小时前
【Temproal】快速了解Temproal的核心概念以及使用
笔记·后端·开源
爱上语文2 小时前
Redis基础(6):SpringDataRedis
数据库·redis·后端
Lemon程序馆2 小时前
速通 GO 垃圾回收机制
后端·go
Aurora_NeAr2 小时前
Spark SQL架构及高级用法
大数据·后端·spark
杰尼橙子2 小时前
DPDK BPF:将eBPF虚拟机的灵活性带入到了DPDK的高性能用户态
后端·性能优化
代码老y2 小时前
Spring Boot + 本地部署大模型实现:优化与性能提升
java·spring boot·后端