AQS原理及流程简述

AQS(AbstractQueuedSynchronizer,抽象队列同步器)是 Java 并发编程中实现锁和同步器的基础框架,其核心思想是通过状态管理等待队列实现线程的同步控制。

一、核心概念

同步状态(State):

  • 一个volatile int 变量,用于表示同步状态(State = 0 表示未锁定;State > 0 表示已锁定)。
  • 通过getState()、setState()、compareAndSetState()等CAS操作进行原子性修改。

等待队列(CLH变体队列):

一个双向链表,用于存储等待获取同步资源的线程。

CLH变体队列中的节点Node:

方法和属性值含义
waitStatus当前节点在队列中的状态
thread表示处于该节点的线程
prev前驱指针
predecessor返回前驱节点,没有的话抛出NullPointerException
nextWaiter指向下一个处于CONDITION(等待唤醒)状态的节点
next后继指针
waitStatus值
含义
0当一个Node被初始化的时候的默认值
CANCELLED为 1 ,表示线程已取消等待(如超时或中断)
CONDITION为 -2 ,表示节点在等待队列中,节点线程等待唤醒
PROPAGATE为 -3 ,当前献策会给你处于SHARED(共享)情况下,该字段才会使用
SIGNAL为 -1 ,表示线程已经准备好了,就等资源释放了

二、核心流程

AQS 的核心操作围绕获取资源和释放资源展开,具体流程如下:

1. 获取资源(Acquire)

线程尝试获取同步资源,若失败则进入等待队列并阻塞。

步骤 1:尝试获取资源

调用tryAcquire(int arg)(由子类实现,如ReentrantLock的非公平锁逻辑):

  • 若成功(如状态修改为锁定),意味着当前线程通过tryAcquire(int arg)方法成功获取到了同步资源的使用权,无需进入等待队列,直接继续执行后续的业务逻辑。
  • 若失败,进入步骤 2。
步骤 2:加入等待队列

创建一个新的Node节点,封装当前线程。
通过 CAS 操作将节点加入队列尾部(确保线程安全)。

步骤 3:阻塞当前线程

节点加入队列后,检查前驱节点状态:

  • 若前驱是头节点再次尝试获取资源成功,则当前节点成为新头节点,线程继续执行。
  • 若失败,即当前线程不具备立即获取资源的条件(要么还没轮到自己,要么轮到了但被其他线程抢占),通过LockSupport.park()阻塞当前线程,并等待被唤醒。

2. 释放资源(Release)

持有资源的线程释放资源,唤醒队列中等待的线程。

步骤 1:尝试释放资源

调用tryRelease(int arg)(由子类实现):

  • 若成功(如状态修改为 0),进入步骤 2。
  • 若失败,即当前线程调用tryRelease(int arg)尝试释放资源时,由于不满足释放条件(如未持有资源、释放次数不匹配等),释放操作失败,此时 AQS 的释放流程直接终止,不会执行后续的 “唤醒等待线程” 步骤。
步骤 2:唤醒等待线程

获取头节点的后继节点(next)。
若后继节点有效(非CANCELLED,没有取消等待),通过LockSupport.unpark(next.thread)唤醒该节点对应的线程。

3. 线程唤醒后的处理

被唤醒的线程从阻塞状态恢复后,会再次尝试获取资源:

  • 若成功,将自己的节点设为新头节点,继续执行。
  • 若失败,重新检查前驱节点状态,必要时再次阻塞(防止虚假唤醒)。

三、AQS 的两种模式

AQS 支持独占模式(如ReentrantLock)和共享模式(如CountDownLatch),流程略有差异:

  • 独占模式:资源只能被一个线程持有(tryAcquire/tryRelease)。
  • 共享模式:资源可被多个线程持有(tryAcquireShared/tryReleaseShared),释放时可能唤醒多个线程。
线程的两种锁模式
模式含义
SHARED表示线程以共享的模式,等待锁
EXCLUSIVE表示线程正在以独占的方式,等待锁

四、总结

AQS 的核心逻辑可概括为:
“状态判断→资源获取 / 释放→队列管理→线程阻塞 / 唤醒”
通过模板方法(acquire/release)定义流程,子类只需实现tryAcquire/tryRelease等抽象方法即可自定义同步逻辑,极大简化了锁和同步器的实现。

(“模板方法” 指的是 AQS 框架已经预先定义好了同步操作的整体流程(骨架),而将流程中需要自定义的具体逻辑(如 “如何获取资源”“如何释放资源”)延迟到子类中实现。
简单说,AQS 就像一个 “半成品框架”:它规定了 “获取资源→入队→阻塞→唤醒→释放资源” 的完整步骤(这就是模板方法),但把其中最关键的 “判断能否获取资源”“如何修改状态” 等细节留给子类去实现。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值