文章目录
- 一、AQS核心概念与设计哲学
-
- [1.1 AQS是什么?](#1.1 AQS是什么?)
- [1.2 AQS的核心数据结构](#1.2 AQS的核心数据结构)
- 二、AQS核心原理深度解析
-
- [2.1 同步状态【state】管理](#2.1 同步状态【state】管理)
- [2.2 CLH队列的工作原理](#2.2 CLH队列的工作原理)
- [2.3 模板方法模式](#2.3 模板方法模式)
- 三、AQS两种同步模式
-
- [3.1 独占模式(Exclusive)](#3.1 独占模式(Exclusive))
-
- [3.1.1 独占模式获取资源](#3.1.1 独占模式获取资源)
- [3.1.2 关键辅助方法解析](#3.1.2 关键辅助方法解析)
- [3.1.3 独占模式释放资源](#3.1.3 独占模式释放资源)
- [3.2 共享模式(Shared)](#3.2 共享模式(Shared))
-
- [3.2.1 共享模式获取资源](#3.2.1 共享模式获取资源)
- [3.2.2 共享模式释放资源](#3.2.2 共享模式释放资源)
- 四、基于AQS的实现示例
-
- [4.1 自定义互斥锁](#4.1 自定义互斥锁)
- [4.2 CustomMutex使用示例](#4.2 CustomMutex使用示例)
- [4.3 不可重入互斥锁(Mutex)](#4.3 不可重入互斥锁(Mutex))
- [4.4 二元信号量(BinarySemaphore)](#4.4 二元信号量(BinarySemaphore))
- [4.5 自定义高级同步器](#4.5 自定义高级同步器)
- 五、AQS在JUC中的实际应用
-
- [5.1 ReentrantLock 中的 AQS 应用](#5.1 ReentrantLock 中的 AQS 应用)
- [5.2 CountDownLatch 中的 AQS 应用](#5.2 CountDownLatch 中的 AQS 应用)
- 六、AQS高级特性
-
-
- [6.1 条件变量(Condition)的实现](#6.1 条件变量(Condition)的实现)
- [6.2 Condition示例](#6.2 Condition示例)
-
- 七、AQS性能优化与最佳实践
-
- [7.1 最佳实践总结](#7.1 最佳实践总结)
- [7.2 使用经验](#7.2 使用经验)
-
- [❌ 避免陷阱](#❌ 避免陷阱)
- 八、总结AQS
一、AQS核心概念与设计哲学
1.1 AQS是什么?
AbstractQueuedSynchronizer(AQS)是 Java 并发包 (java.util.concurrent.locks
) 中的核心框架,用于构建锁和其他同步器的基础。它提供了一个基于 FIFO 等待队列的同步器框架,JUC 中的大多数同步工具如 ReentrantLock、Semaphore、CountDownLatch 都是基于 AQS 构建的。
核心设计思想:
- 状态管理:使用一个 volatile int 类型的 state 变量表示同步状态
- 队列管理:通过内置的 FIFO 队列管理获取同步状态失败的线程
- 模板方法:通过模板方法模式,子类通过继承并实现指定方法管理同步状态
基于AQS的实现 AQS 核心架构 ReentrantLock Semaphore CountDownLatch CyclicBarrier ReentrantReadWriteLock AQS volatile int state
同步状态 CLH队列
FIFO线程等待队列 独占模式
如ReentrantLock 共享模式
如Semaphore
1.2 AQS的核心数据结构
java
// AQS 简化核心结构
public abstract class AbstractQueuedSynchronizer {
// 同步状态,volatile保证可见性
private volatile int state;
// CLH队列头节点
private transient volatile Node head;
// CLH队列尾节点
private transient volatile Node tail;
// CLH队列节点定义
static final class Node {
// 节点模式:共享、独占
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
// 等待状态
volatile int waitStatus;
// 前驱和后继节点
volatile Node prev;
volatile Node next;
// 节点关联的线程
volatile Thread thread;
}
}
二、AQS核心原理深度解析
组件 | 说明 |
---|---|
state |
int 类型,表示同步状态。由 volatile 修饰,保证可见性。 |
head / tail |
指向同步队列的头节点和尾节点。 |
Node |
队列中的节点,封装等待线程及其等待状态。 |
CLH 队列变体 |
AQS 使用的是 CLH 锁队列的变体,用于管理等待线程。 |
2.1 同步状态【state】管理
AQS 使用一个整型的 state 来表示同步状态,不同的子类对其有不同的解释:
- ReentrantLock:state 表示锁的重入次数(0表示未锁定,>0表示重入次数)
- Semaphore:state 表示可用的许可数量
- CountDownLatch:state 表示计数器值
- ReentrantReadWriteLock:高16位表示读锁数量,低16位表示写锁重入次数
2.2 CLH队列的工作原理
AQS 使用 CLH 变体的双向队列来管理等待线程。CLH 队列是一个 FIFO 队列,具有以下特性:
- 公平性:保证等待时间最长的线程最先获取锁
- 高效性:通过前驱节点的状态来减少不必要的线程唤醒
- 可扩展性:支持大量线程的排队管理
node的节点结构
java
static final class Node {
volatile int waitStatus; // 等待状态
volatile Node prev; // 前驱节点
volatile Node next; // 后继节点
volatile Thread thread; // 关联的线程
Node nextWaiter; // 下一个等待节点(用于条件队列)
}
等待状态的值
状态 | 值 | 含义 |
---|---|---|
SIGNAL |
-1 | 当前节点的后继节点已被阻塞,需要当前节点释放时唤醒它。 |
CANCELLED |
1 | 线程已取消(如中断或超时)。 |
CONDITION |
-2 | 节点在条件队列中。 |
PROPAGATE |
-3 | 共享模式下,释放操作应传播到后续节点。 |
同步队列结构
AQS 同步队列 Node: Thread A head Node: Thread B Node: Thread C tail
说明 :队列为双向链表,head
是虚拟头节点(不关联线程),tail
指向最后一个真实节点。
java
// CLH队列操作的核心方法
private Node addWaiter(Node mode) {
// 创建新节点,包含当前线程和模式(独占/共享)
Node node = new Node(Thread.currentThread(), mode);
// 快速尝试添加到队列尾部
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// 如果快速添加失败,使用完整入队流程
enq(node);
return node;
}
private Node enq(final Node node) {
for (;;) { // 自旋直到成功入队
Node t = tail;
if (t == null) { // 队列为空,需要初始化
if (compareAndSetHead(new Node())) // 设置哑节点
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
2.3 模板方法模式
AQS 使用模板方法模式,子类需要实现以下关键方法:
java
public abstract class AbstractQueuedSynchronizer {
// 尝试获取独占锁,需要子类实现
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
// 尝试释放独占锁,需要子类实现
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
// 尝试获取共享锁,需要子类实现
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
// 尝试释放共享锁,需要子类实现
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
// 判断是否独占模式,需要子类实现
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
}
三、AQS两种同步模式
3.1 独占模式(Exclusive)
一次只有一个线程可以获取同步状态,如 ReentrantLock。
java
// 独占模式获取同步状态的核心流程
public final void acquire(int arg) {
if (!tryAcquire(arg) && // 首先尝试获取
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 失败则加入队列
selfInterrupt(); // 如果等待过程中被中断,重新设置中断标志
}
// 独占模式获取同步状态的详细流程
public final void acquire(int arg) {
if (!tryAcquire(arg)) { // 尝试获取锁失败
Node node = addWaiter(Node.EXCLUSIVE); // 创建独占模式节点并入队
boolean interrupted = false;
for (;;) { // 自旋
final Node p = node.predecessor(); // 获取前驱节点
if (p == head && tryAcquire(arg)) { // 如果前驱是头节点且获取成功
setHead(node); // 将自己设为头节点
p.next = null; // 帮助GC
return;
}
if (shouldParkAfterFailedAcquire(p, node) && // 检查是否需要park
parkAndCheckInterrupt()) // park并检查中断
interrupted = true;
}
}
}
独占模式获取锁流程

独占模式释放锁
成功 失败 线程调用 release(int arg) tryRelease(arg) unparkSuccessor(head) 获取 head 的 next 节点 LockSupport.unpark(next.thread) 唤醒线程继续执行 acquireQueued 释放失败
特点 :同一时间只有一个线程能获取同步资源(如ReentrantLock
的独占锁)。
核心流程
:线程获取资源→成功则执行→失败则加入等待队列并阻塞→资源释放后唤醒队列中的下一个线程。
3.1.1 独占模式获取资源
acquire (int arg)
acquire
是 AQS 提供的模板方法,子类无需重写,直接调用即可。流程如下:
-
调用子类重写的tryAcquire(arg)
尝试获取资源:
- 成功:直接返回,线程继续执行;
- 失败:执行后续步骤。
-
调用
addWaiter(Node.EXCLUSIVE)
创建独占模式的Node
节点,并加入队列尾部; -
调用
acquireQueued(node, arg)
让节点在队列中自旋等待,直到获取资源或被取消。
简化后的核心代码:
java
public final void acquire(int arg) {
// 1. 尝试获取资源,失败则加入队列并自旋等待
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
// 若自旋过程中被中断,标记当前线程需要中断
selfInterrupt();
}
}
3.1.2 关键辅助方法解析
- tryAcquire(int arg)
抽象方法,由子类实现,定义 "如何获取资源" 的逻辑。AQS 中默认抛出UnsupportedOperationException
,子类必须重写(如ReentrantLock
)。示例(非公平锁的tryAcquire
实现)
java
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
// 1. 若状态为0(无锁),尝试CAS获取锁
if (c == 0) {
if (compareAndSetState(0, acquires)) {
// 2. 标记当前线程为锁持有者
setExclusiveOwnerThread(current);
return true;
}
}
// 3. 若当前线程已持有锁(重入),增加state计数
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // 防止溢出
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
// 4. 其他情况,获取失败
return false;
}
- addWaiter(Node mode)
创建节点并加入队列尾部(CAS 保证线程安全),流程如下:
java
private Node addWaiter(Node mode) {
// 1. 创建当前线程的Node节点(mode为EXCLUSIVE或SHARED)
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
// 2. 若队列不为空,直接尝试CAS将节点加入尾部
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
// 3. 队列为空或CAS失败,通过enq方法自旋加入队列
enq(node);
return node;
}
// 自旋CAS加入队列,确保节点被成功添加
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // 队列空,初始化头节点(虚拟节点)
if (compareAndSetHead(new Node()))
tail = head;
} else { // 队列非空,CAS添加到尾部
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
- acquireQueued(final Node node, int arg)
节点在队列中自旋等待,核心逻辑是 "前驱节点是头节点时,再次尝试获取资源;否则阻塞当前线程",流程如下:
java
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
// 自旋循环,直到获取资源或被取消
for (;;) {
final Node p = node.predecessor(); // 获取前驱节点
// 1. 若前驱是头节点,尝试获取资源
if (p == head && tryAcquire(arg)) {
setHead(node); // 2. 获取成功,将当前节点设为头节点(原头节点被GC回收)
p.next = null; // 3. 断开原头节点的引用,避免内存泄漏
failed = false;
return interrupted; // 4. 返回是否被中断过
}
// 5. 若获取失败,判断是否需要阻塞当前线程
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) {
// 6. 若线程被中断,标记interrupted为true
interrupted = true;
}
}
} finally {
if (failed) {
// 7. 若获取资源失败且发生异常,取消当前节点
cancelAcquire(node);
}
}
}
其中,shouldParkAfterFailedAcquire
方法用于设置前驱节点的状态为SIGNAL
,确保后续能被唤醒;parkAndCheckInterrupt
方法通过LockSupport.park(this)
阻塞当前线程,并返回是否被中断。
3.1.3 独占模式释放资源
release (int arg)
release
也是模板方法,用于释放资源并唤醒队列中的下一个线程,流程如下:
-
调用子类重写的tryRelease(arg)
尝试释放资源:
- 成功:执行后续步骤;
- 失败:直接返回
false
。
-
唤醒队列中的下一个节点(若存在)。
简化后的核心代码
java
public final boolean release(int arg) {
// 1. 尝试释放资源
if (tryRelease(arg)) {
Node h = head;
// 2. 若头节点不为空且状态不是初始状态,唤醒下一个节点
if (h != null && h.waitStatus != 0) {
unparkSuccessor(h);
}
return true;
}
return false;
}
tryRelease 示例(ReentrantLock 实现):
java
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
// 1. 只有锁持有者才能释放锁
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 2. 若state减为0,说明锁已完全释放
if (c == 0) {
free = true;
setExclusiveOwnerThread(null); // 清除锁持有者
}
setState(c); // 更新状态
return free;
}
unparkSuccessor 方法 :唤醒头节点的后继节点(跳过CANCELLED
状态的节点),核心逻辑是通过LockSupport.unpark(s.thread)
唤醒线程。
3.2 共享模式(Shared)
特点 :同一时间多个线程可同时获取同步资源(如Semaphore
、CountDownLatch
)。
核心流程与独占模式类似,但差异在于:
- 共享模式下,线程获取资源成功后,会继续唤醒后续等待的共享线程(如
CountDownLatch
的countDown
后,所有等待线程被唤醒); - 核心方法为
acquireShared(int arg)
(获取资源)和releaseShared(int arg)
(释放资源)。
java
// 共享模式获取同步状态
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0) // 尝试获取
doAcquireShared(arg); // 失败则加入队列
}
// 共享模式获取的详细实现
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED); // 创建共享模式节点
boolean interrupted = false;
try {
for (;;) { // 自旋
final Node p = node.predecessor(); // 前驱节点
if (p == head) {
int r = tryAcquireShared(arg); // 尝试获取共享锁
if (r >= 0) { // 获取成功
setHeadAndPropagate(node, r); // 设置头节点并传播
p.next = null; // 帮助GC
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (interrupted)
selfInterrupt();
}
}
释放共享资源 获取共享资源 是 否 是 成功 tryReleaseShared(arg) releaseShared(arg) doReleaseShared() 唤醒 head.next 若为共享节点, 继续传播 tryAcquireShared(arg) >= 0 acquireShared(arg) 获取成功 doAcquireShared(arg) addWaiter(SHARED) 自旋 + 尝试获取 获取成功? setHeadAndPropagate() 传播唤醒后续共享节点
3.2.1 共享模式获取资源
acquireShared (int arg)
模板方法,流程如下:
-
调用子类重写的tryAcquireShared(arg)
尝试获取资源:
- 返回值
>=0
:获取成功,返回; - 返回值
<0
:获取失败,加入队列并阻塞。
- 返回值
-
若获取失败,调用
doAcquireShared(arg)
将节点加入队列并自旋等待。
简化后的核心代码
java
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0) {
doAcquireShared(arg); // 加入队列并自旋
}
}
tryAcquireShared 示例(Semaphore 实现)
java
protected int tryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
// 1. 若可用许可不足,或CAS修改许可失败,继续自旋
if (remaining < 0 ||
compareAndSetState(available, remaining)) {
return remaining; // 返回剩余许可(<0表示获取失败)
}
}
}
3.2.2 共享模式释放资源
releaseShared (int arg)
模板方法,流程如下:
- 调用子类重写的
tryReleaseShared(arg)
尝试释放资源(CAS 确保原子性); - 若释放成功,唤醒队列中的后续共享节点。
简化后的核心代码
java
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared(); // 唤醒后续节点
return true;
}
return false;
}
tryReleaseShared 示例(Semaphore 实现)
java
protected final boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (next < current) // 防止溢出
throw new Error("Maximum permit count exceeded");
// CAS修改许可数量,成功则返回true
if (compareAndSetState(current, next))
return true;
}
}
四、基于AQS的实现示例
4.1 自定义互斥锁
java
package cn.tcmeta.aqs;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* 基于AQS的自定义互斥锁实现
* 演示AQS独占模式的基本用法
*/
public class CustomMutex implements Lock {
private final Sync sync = new Sync();
// 自定义同步器,继承AQS
private static class Sync extends AbstractQueuedSynchronizer {
// 是否被占用
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
// 尝试获取锁
@Override
public boolean tryAcquire(int acquires) {
// 使用CAS操作尝试将state从0改为1
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread()); // 设置独占线程
return true;
}
return false;
}
// 尝试释放锁
@Override
protected boolean tryRelease(int releases) {
if (getState() == 0)
throw new IllegalMonitorStateException("锁未被当前线程持有");
setExclusiveOwnerThread(null); // 清除独占线程
setState(0); // 释放锁
return true;
}
// 创建条件变量
Condition newCondition() {
return new ConditionObject();
}
}
// Lock接口方法实现
@Override
public void lock() {
sync.acquire(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return sync.newCondition();
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
}
4.2 CustomMutex使用示例
java
package cn.tcmeta.aqs;
import java.util.concurrent.CountDownLatch;
/**
* AQS自定义锁使用示例
*/
public class AQSExample {
private final CustomMutex mutex = new CustomMutex();
private int sharedResource = 0;
public void demonstrateMutex() throws InterruptedException {
// 创建多个线程竞争访问共享资源
int threadCount = 5;
CountDownLatch startLatch = new CountDownLatch(1);
CountDownLatch endLatch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
final int threadId = i;
new Thread(() -> {
try {
startLatch.await(); // 等待开始信号
// 使用自定义互斥锁保护临界区
mutex.lock();
try {
System.out.println("线程 " + threadId + " 获取锁,共享资源: " + sharedResource);
sharedResource++;
Thread.sleep(100); // 模拟工作
} finally {
mutex.unlock();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
endLatch.countDown();
}
}).start();
}
startLatch.countDown(); // 开始所有线程
endLatch.await(); // 等待所有线程完成
System.out.println("最终共享资源值: " + sharedResource);
}
static void main(String[] args) throws InterruptedException {
AQSExample example = new AQSExample();
example.demonstrateMutex();
}
}

4.3 不可重入互斥锁(Mutex)
java
package cn.tcmeta.aqs;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* 基于 AQS 实现的不可重入互斥锁
* state = 0: 未加锁, state = 1: 已加锁
*/
public class Mutex {
private static class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int acquires) {
// 仅当 state 为 0 时,通过 CAS 获取锁
return compareAndSetState(0, 1);
}
@Override
protected boolean tryRelease(int releases) {
// 释放锁,设置 state 为 0
setState(0);
return true;
}
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
}
private final Sync sync = new Sync();
public void lock() {
sync.acquire(1);
}
public void unlock() {
sync.release(1);
}
public boolean tryLock() {
return sync.tryAcquire(1);
}
}
4.4 二元信号量(BinarySemaphore)
java
package cn.tcmeta.aqs;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* 二元信号量:只有 0 或 1 个许可
*/
public class BinarySemaphore {
private static class Sync extends AbstractQueuedSynchronizer {
Sync(int permits) {
setState(permits); // 初始化许可数
}
@Override
protected int tryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 || compareAndSetState(available, remaining)) {
return remaining;
}
}
}
@Override
protected boolean tryReleaseShared(int releases) {
for (;;) {
int current = getState();
int next = current + releases;
if (compareAndSetState(current, next)) {
return true;
}
}
}
}
private final Sync sync;
public BinarySemaphore(int permits) {
if (permits < 0) throw new IllegalArgumentException();
this.sync = new Sync(permits);
}
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public void release() {
sync.releaseShared(1);
}
}
4.5 自定义高级同步器
支持超时等待锁
java
/**
* 支持超时等待的自定义锁
* 演示AQS高级用法
*/
public class TimeoutMutex implements Lock {
private final Sync sync = new Sync();
private static class Sync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int acquires) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int releases) {
if (getState() == 0)
throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
// 添加超时获取方法
public boolean tryAcquireNanos(int acquires, long nanosTimeout)
throws InterruptedException {
return tryAcquire(acquires) ||
doAcquireNanos(acquires, nanosTimeout);
}
}
@Override
public void lock() {
sync.acquire(1);
}
@Override
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
// 其他方法实现...
}
五、AQS在JUC中的实际应用
5.1 ReentrantLock 中的 AQS 应用
java
/**
* ReentrantLock中AQS应用分析
*/
public class ReentrantLock implements Lock {
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {
// 非公平锁尝试获取
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) { // 锁未被占用
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { // 重入
int nextc = c + acquires;
if (nextc < 0) throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
@Override
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
}
// 非公平锁实现
static final class NonfairSync extends Sync {
@Override
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
// 公平锁实现
static final class FairSync extends Sync {
@Override
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() && // 检查是否有前驱节点(公平性)
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) { // 重入
int nextc = c + acquires;
if (nextc < 0) throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
}
5.2 CountDownLatch 中的 AQS 应用
java
/**
* CountDownLatch中AQS应用分析
*/
public class CountDownLatch {
private static final class Sync extends AbstractQueuedSynchronizer {
Sync(int count) {
setState(count); // 初始化计数器
}
int getCount() {
return getState();
}
// 共享模式尝试获取
@Override
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
// 共享模式尝试释放
@Override
protected boolean tryReleaseShared(int releases) {
for (;;) { // 自旋直到成功
int c = getState();
if (c == 0) return false; // 已经为0,不需要释放
int nextc = c - 1;
if (compareAndSetState(c, nextc)) // CAS更新状态
return nextc == 0; // 返回是否达到0
}
}
}
private final Sync sync;
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public void countDown() {
sync.releaseShared(1);
}
}
六、AQS高级特性
6.1 条件变量(Condition)的实现
AQS 内部类ConditionObject
实现了Condition
接口,提供了类似Object.wait()
/notify()
的等待 / 通知机制,但更灵活(一个锁可关联多个条件队列)
ConditionObject
是 AQS 的内部类。- 每个
Condition
对应一个条件等待队列(单向链表)。 await()
:当前线程释放锁,加入条件队列,阻塞。signal()
:将条件队列首节点转移到同步队列,等待获取锁。
线程调用 condition.await() 释放锁 加入条件队列 阻塞 signal() 转移节点到同步队列 线程被唤醒, 重新竞争锁
示例流程:
- 线程获取锁后调用
condition.await()
,释放锁并进入条件队列; - 其他线程调用
condition.signal()
,将条件队列的节点移至主队列; - 主队列中的节点按规则竞争锁,获取锁后继续执行。
6.2 Condition示例
java
/**
* AQS条件变量使用示例
*/
public class ConditionExample {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private boolean conditionMet = false;
public void awaitCondition() throws InterruptedException {
lock.lock();
try {
while (!conditionMet) { // 条件检查,防止虚假唤醒
System.out.println("条件未满足,线程进入等待...");
condition.await(); // 释放锁并等待
}
// 条件满足,执行操作
System.out.println("条件满足,继续执行...");
} finally {
lock.unlock();
}
}
public void signalCondition() {
lock.lock();
try {
conditionMet = true;
System.out.println("条件已满足,唤醒等待线程...");
condition.signal(); // 唤醒一个等待线程
} finally {
lock.unlock();
}
}
public void signalAllCondition() {
lock.lock();
try {
conditionMet = true;
System.out.println("条件已满足,唤醒所有等待线程...");
condition.signalAll(); // 唤醒所有等待线程
} finally {
lock.unlock();
}
}
}
七、AQS性能优化与最佳实践
7.1 最佳实践总结
- 正确实现模板方法 :
- 确保
tryAcquire
/tryRelease
等方法的线程安全性 - 正确管理同步状态 (state)
- 确保
- 合理选择同步模式 :
- 独占模式:互斥访问资源(如锁)
- 共享模式:多个线程可同时访问(如信号量)
- 避免常见陷阱 :
- 正确处理中断
- 避免死锁
- 注意内存可见性
- 性能考虑 :
- 减少不必要的 CAS 操作
- 合理使用自旋等待
- 考虑公平性 vs 吞吐量权衡
7.2 使用经验
✅ 正确使用
-
优先使用标准同步器 :如
ReentrantLock
,避免重复造轮子。 -
钩子方法保持轻量 :避免在
tryAcquire
中执行复杂逻辑。 -
正确处理中断 :在
acquireQueued
中检查中断状态。 -
避免死锁 :确保
tryRelease
一定能成功释放
❌ 避免陷阱
- 不要在持有锁时调用阻塞操作(如 I/O)。
- 不要重写 AQS 的模板方法 (如
acquire
),只重写钩子。 - 避免在
tryRelease
中抛出异常,否则队列无法唤醒
八、总结AQS
AQS 的成功源于其分层设计思想:
- 底层:基于 CAS + volatile + LockSupport 实现无锁并发
- 中层:CLH 队列管理线程排队
- 上层:模板方法 + 钩子方法 提供扩展点
一句话总结:
- AQS 是 Java 并发的"操作系统内核"------它不直接提供服务,而是为构建锁、信号量、门闩等"进程"提供统一的调度、内存和中断机制。
AQS 是 Java 并发编程的基石,其通过状态变量(state) 、FIFO 等待队列 和模板方法模式,为同步工具的实现提供了统一框架。理解 AQS 的核心原理,不仅能帮助我们更好地使用 JDK 中的并发工具,还能在需要时自定义高效的同步器。
AQS 的设计体现了 "高内聚、低耦合" 的思想:将复杂的队列管理、线程阻塞 / 唤醒等通用逻辑封装在抽象类中,子类只需关注具体的同步规则。这种设计极大地降低了并发组件的开发难度,也保证了这些组件在性能和可靠性上的一致性。
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
往期资料:
链接: https://pan.baidu.com/s/13wJhUxSVY2pbWOgjuIzWtg 提取码: dhq8
点击获取往期资料合集
提取码: dhq8
✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅