一、CAS(Compare And Swap)
1. 基本概念
CAS 是一种乐观锁实现,包含三个操作数:
- 内存值 V(当前主内存中的值)
- 预期值 A(线程本地记录的旧值)
- 新值 B(要更新的值)
核心逻辑:只有当 V == A 时,才将 V 更新为 B,否则重试。
2. 底层实现
java
// Unsafe 类中的 CAS 操作(底层调用 CPU 指令)
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
硬件层面:现代 CPU 提供 cmpxchg 指令(x86)或 LDREX/STREX(ARM),保证操作的原子性。
3. 典型应用
| 类 | 说明 |
|---|---|
AtomicInteger / AtomicLong |
原子整型 |
AtomicReference |
原子引用 |
AtomicStampedReference |
解决 ABA 问题(带版本号) |
ConcurrentHashMap |
分段锁 + CAS 优化 |
ABA 问题
问题描述 :值从 A → B → A,CAS 检测不出变化。
解决方案:AtomicStampedReference 增加版本号/时间戳。
java
AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(100, 0);
int[] stampHolder = new int[1];
Integer value = ref.get(stampHolder); // 获取值和版本号
ref.compareAndSet(100, 200, stampHolder[0], stampHolder[0] + 1);
5. CAS 的优缺点
| 优点 | 缺点 |
|---|---|
| 无锁,性能高(无线程切换开销) | 只能保证单个变量的原子性 |
| 非阻塞,不会死锁 | 循环重试消耗 CPU(自旋) |
| 存在 ABA 问题 |
二、AQS(AbstractQueuedSynchronizer)
1. 基本概念
AQS 是 JUC 并发包的基石 ,是一个用于构建锁和同步器的抽象框架 。
核心设计:
- state 变量:int 类型,表示同步状态(如重入锁的重入次数、信号量的许可数)
- FIFO 队列:CLH 变体的双向链表,管理等待线程
- 模板方法模式:子类只需实现特定方法
2. 核心结构

3. 两种模式
| 模式 | 说明 | 代表类 |
|---|---|---|
| 独占模式 | 同一时间只有一个线程能获取 | ReentrantLock |
| 共享模式 | 多个线程可同时获取 | Semaphore、CountDownLatch |
4. 核心方法(子类需实现)
java
// 独占模式
protected boolean tryAcquire(int arg); // 获取锁
protected boolean tryRelease(int arg); // 释放锁
// 共享模式
protected int tryAcquireShared(int arg); // 获取共享锁
protected boolean tryReleaseShared(int arg); // 释放共享锁
// 通用
protected boolean isHeldExclusively(); // 是否被独占
5. 队列节点(Node)状态
| 状态 | 值 | 含义 |
|---|---|---|
CANCELLED |
1 | 节点被取消(超时或中断) |
SIGNAL |
-1 | 后继节点需要被唤醒 |
CONDITION |
-2 | 在 Condition 队列中 |
PROPAGATE |
-3 | 共享模式传播 |
6. 获取锁的流程(以 ReentrantLock 为例)

7. 核心源码分析
java
// AQS 获取锁的入口
public final void acquire(int arg) {
if (!tryAcquire(arg) && // 1. 快速尝试获取
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 2. 入队 + 排队获取
selfInterrupt(); // 3. 恢复中断状态
}
// 入队操作(CAS 保证线程安全)
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)) { // CAS 入队
pred.next = node;
return node;
}
}
enq(node); // 初始化或重试
return node;
}
8. AQS 应用
| 同步器 | 模式 | 用途 |
|---|---|---|
ReentrantLock |
独占 | 可重入互斥锁 |
ReentrantReadWriteLock |
独占+共享 | 读写分离锁 |
Semaphore |
共享 | 限流/资源池 |
CountDownLatch |
共享 | 等待多线程完成 |
CyclicBarrier |
共享 | 线程互相等待 |
Phaser |
共享 | 分阶段任务 |
三、CAS vs AQS
| 维度 | CAS | AQS |
|---|---|---|
| 层级 | 底层原子操作 | 上层同步框架 |
| 机制 | 乐观锁(无锁) | 悲观锁 + 队列 |
| 适用场景 | 简单变量更新 | 复杂同步控制 |
| 线程冲突 | 重试(自旋) | 阻塞( park/unpark ) |
| CPU 消耗 | 高冲突时较高 | 阻塞后较低 |
| 关系 | AQS 内部用 CAS 维护 state 和队列 |
四、实际应用
1. 基于 CAS 的原子计数器
java
AtomicInteger counter = new AtomicInteger(0);
// 底层:CAS 循环直到成功
counter.incrementAndGet();
基于 AQS 的自定义锁
java
class SimpleLock extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
return compareAndSetState(0, 1); // CAS 修改 state
}
@Override
protected boolean tryRelease(int arg) {
setState(0);
return true;
}
public void lock() { acquire(1); }
public void unlock() { release(1); }
}
五、总结
- CAS 是 Java 实现无锁并发的底层利器,适用于低竞争、简单场景
- AQS 是构建复杂同步器的框架,通过 state + CLH 队列 + CAS 实现了高效的线程阻塞与唤醒
- 两者相辅相成:AQS 内部大量依赖 CAS 操作(如 compareAndSetState、compareAndSetTail)