Java 并发包核心机制深度解析:锁的公平性、异步调度、AQS 原理全解
🧠 Java 并发包核心机制深度解析:锁的公平性、异步调度、AQS 原理全解
Java 并发编程的地基是 java.util.concurrent
,但真正驱动这个系统的,是它背后隐藏的三根支柱:
- ReentrantLock 的公平/非公平调度策略
- CompletableFuture 的异步执行模型
- AQS 的队列与阻塞线程管理机制
本文将以源码 & 结构视角解析这三块知识点,并配图讲清它们的运行状态与机制。
🔐 ReentrantLock 公平锁 vs 非公平锁
✳️ 概念区别
- 公平锁(Fair):排队等待的线程会按顺序获取锁,避免“插队”。
- 非公平锁(NonFair):新线程尝试直接 CAS 获取锁,如果成功就跳过队列 —— 提升吞吐量,但可能导致“饿死”。
📜 构造方式
// 默认是非公平锁
Lock lock = new ReentrantLock(); // 公平锁
Lock fairLock = new ReentrantLock(true);
⚙️ 实现原理
ReentrantLock 继承自 AbstractQueuedSynchronizer
(AQS),关键方法如下:
// 非公平:直接尝试 CAS 抢锁
final boolean nonfairTryAcquire(int acquires) {final Thread current = Thread.currentThread();int c = getState();if (c == 0 && compareAndSetState(0, acquires)) {setExclusiveOwnerThread(current);return true;}return false;
}// 公平:要先检查前面有没有排队线程
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;}}return false;
}
🔁 锁状态图
[Free Lock] → tryAcquire()↓ ↘ (被占用)
[Acquired] → 加入 AQS 等待队列 → LockSupport.park() 阻塞↓unlock() → 唤醒队列中的下一个线程
🚀 CompletableFuture 的异步调度机制
CompletableFuture
是 JDK 8 提供的函数式异步编程工具,常用于构建任务链和异步合并。
🧱 内部结构
CompletableFuture<T> {Object result;volatile Completion stack; // 任务链
}
每一个 thenApply
, thenAccept
, thenCombine
等方法,本质上是构建一个任务节点(Completion),放入队列中。
🔧 异步调度流程
CompletableFuture.supplyAsync(() -> {return 42;
}).thenApplyAsync(res -> {return res + 1;
});
supplyAsync()
提交任务到默认线程池(ForkJoinPool.commonPool)- 任务执行完成后,触发
postComplete()
,依次唤醒后续 Completion - 后续任务如果带
Async
,会再次提交到线程池执行,否则同步调用
☑️ 核心调度代码
private void postComplete() {Completion h;while ((h = stack) != null) {if (UNSAFE.compareAndSwapObject(this, STACK, h, null))h.tryFire(NESTED);}
}
Completion
是内部静态类,代表任务节点链表,构成任务依赖树。
🧱 AQS:并发核心队列结构
AbstractQueuedSynchronizer
是整个 locks
与 同步器
的基石,核心是管理同步状态与阻塞线程。
🧬 AQS 结构图
+-----------------------+
| AbstractQueuedSynchronizer |
+-----------------------+
| int state |
| Node head |
| Node tail |
+-----------------------+Node {Thread thread;Node next;Node prev;int waitStatus; // SIGNAL, CANCELLED...
}
🔁 加锁过程(独占)
- 尝试获取锁(CAS 设置 state)
- 失败则入队(构造 Node,放入队列)
- 阻塞线程(LockSupport.park)
- 被唤醒后再次尝试获取锁
✨ 解锁过程
- CAS 修改 state,释放锁
- 唤醒队列中第一个
SIGNAL
状态的 Node(即下一个等待线程) - 线程继续执行
🎯 总结:三者协作关系
模块 | 角色 | 底层依赖 |
---|---|---|
ReentrantLock | 负责线程互斥、资源保护 | AQS + LockSupport |
CompletableFuture | 异步任务链式调度 | ForkJoinPool + Completion |
AQS | 管理线程队列、状态、阻塞机制 | CAS + LockSupport + Unsafe |
## 🧩 附图:Java 并发包知识导图