Java并发编程进阶:深度剖析Atomic、CAS与AQS实现原理
引言:现代并发编程的基石
在多核处理器时代,高效并发控制是提升系统性能的关键。Java并发包(JUC)中的三大核心技术——Atomic原子类、CAS机制和AQS框架,构成了现代并发编程的基础设施。本文将通过原理剖析、源码解读和实战案例,带你深入理解这些核心技术的实现机制。
一、核心概念全景解析
1.1 Atomic原子类体系
实现原理:
类继承体系:
- 基础类型:AtomicInteger/AtomicLong/AtomicBoolean
- 引用类型:AtomicReference/AtomicStampedReference
- 数组类型:AtomicIntegerArray/AtomicLongArray
- 字段更新:AtomicIntegerFieldUpdater
内存可见性保障:
// AtomicInteger源码片段
public class AtomicInteger extends Number {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private volatile int value; // volatile保证可见性
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
}
1.2 CAS机制深度探秘
CPU指令级实现:
- x86架构:CMPXCHG指令
- ARM架构:LL/SC指令对
ABA问题解决方案:
// 使用AtomicStampedReference解决ABA问题
AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);
int[] stampHolder = new int[1];
String current = ref.get(stampHolder);
ref.compareAndSet(current, "B", stampHolder[0], stampHolder[0]+1);
CAS性能优化策略:
- 自适应自旋(JVM实现)
- 批量操作(LongAdder的分段统计)
- 退避策略(指数退避算法)
1.3 AQS框架设计
CLH队列实现:
状态管理机制:
- 同步状态(state):volatile int类型
- 节点状态(waitStatus):
- CANCELLED(1)
- SIGNAL(-1)
- CONDITION(-2)
- PROPAGATE(-3)
二、关键技术实现剖析
2.1 Atomic原子类高效实现
缓存行优化:
// LongAdder的Cell类使用@Contended避免伪共享
@sun.misc.Contended
static final class Cell {
volatile long value;
// ...
}
分段计数原理:
2.2 AQS实现可重入锁
ReentrantLock类结构:
public class ReentrantLock implements Lock {
private final Sync sync; // 继承自AQS
abstract static class Sync extends AbstractQueuedSynchronizer {
// 实现tryAcquire等模板方法
}
}
获取锁流程:
三、实战开发案例集
3.1 CAS 实战代码
ABA 问题解决方案
使用版本号(AtomicStampedReference)
import java.util.concurrent.atomic.AtomicStampedReference;
public class ABASolutionWithStamp {
public static void main(String[] args) {
// 使用 AtomicStampedReference 解决 ABA 问题
AtomicStampedReference<String> ref = new AtomicStampedReference<>("A", 0);
int[] stampHolder = new int[1];
String current = ref.get(stampHolder);
// 模拟 ABA 操作
ref.compareAndSet(current, "B", stampHolder[0], stampHolder[0] + 1);
ref.compareAndSet("B", "A", stampHolder[0] + 1, stampHolder[0] + 2);
// 再次尝试更新
if (ref.compareAndSet(current, "C", stampHolder[0], stampHolder[0] + 1)) {
System.out.println("更新成功");
} else {
System.out.println("更新失败,可能发生了 ABA 问题");
}
}
}
使用 AtomicMarkableReference
import java.util.concurrent.atomic.AtomicMarkableReference;
public class ABASolutionWithMark {
public static void main(String[] args) {
// 使用 AtomicMarkableReference 解决 ABA 问题
AtomicMarkableReference<String> ref = new AtomicMarkableReference<>("A", false);
boolean[] markHolder = new boolean[1];
String current = ref.get(markHolder);
// 模拟 ABA 操作
ref.compareAndSet(current, "B", markHolder[0], !markHolder[0]);
ref.compareAndSet("B", "A", !markHolder[0], markHolder[0]);
// 再次尝试更新
if (ref.compareAndSet(current, "C", markHolder[0], !markHolder[0])) {
System.out.println("更新成功");
} else {
System.out.println("更新失败,可能发生了 ABA 问题");
}
}
}
CAS 性能优化策略
自适应自旋(JVM 实现)
JVM 会根据当前系统的状态自动调整自旋的次数,避免长时间的自旋消耗过多的 CPU 资源。以下是一个简单的示例,模拟自适应自旋的效果:
import java.util.concurrent.atomic.AtomicInteger;
public class AdaptiveSpinExample {
private static AtomicInteger counter = new AtomicInteger(0);
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (true) {
int expect = counter.get();
if (counter.compareAndSet(expect, expect + 1)) {
System.out.println("线程 1 更新成功,当前值: " + counter.get());
break;
}
// 模拟自适应自旋,可根据实际情况调整自旋次数
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Thread t2 = new Thread(() -> {
while (true) {
int expect = counter.get();
if (counter.compareAndSet(expect, expect + 1)) {
System.out.println("线程 2 更新成功,当前值: " + counter.get());
break;
}
// 模拟自适应自旋,可根据实际情况调整自旋次数
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
批量操作(LongAdder 的分段统计)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.LongAdder;
public class LongAdderExample {
public static void main(String[] args) throws InterruptedException {
LongAdder adder = new LongAdder();
ExecutorService executor = Executors.newFixedThreadPool(10);
// 模拟多线程并发增加操作
for (int i = 0; i < 1000; i++) {
executor.submit(() -> {
adder.increment();
});
}
executor.shutdown();
while (!executor.isTerminated()) {
// 等待所有任务完成
}
System.out.println("最终结果: " + adder.sum());
}
}
退避策略(指数退避算法)
import java.util.concurrent.ThreadLocalRandom;
class Backoff {
final int minDelay, maxDelay;
int limit;
public Backoff(int minDelay, int maxDelay) {
this.minDelay = minDelay;
this.maxDelay = maxDelay;
this.limit = minDelay;
}
public void backoff() throws InterruptedException {
int delay = ThreadLocalRandom.current().nextInt(limit);
limit = Math.min(maxDelay, limit * 2);
Thread.sleep(delay);
}
}
public class BackoffExample {
private static final int MIN_DELAY = 1;
private static final int MAX_DELAY = 100;
private static final int ATTEMPTS = 10;
public static void main(String[] args) {
Backoff backoff = new Backoff(MIN_DELAY, MAX_DELAY);
for (int i = 0; i < ATTEMPTS; i++) {
try {
// 模拟 CAS 操作失败
if (!simulateCAS()) {
System.out.println("CAS 操作失败,尝试退避...");
backoff.backoff();
} else {
System.out.println("CAS 操作成功");
break;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static boolean simulateCAS() {
// 模拟 CAS 操作失败的概率
return Math.random() > 0.5;
}
}
通过以上内容,我们对原文档中的 CAS 实践进行了完善,涵盖了更多的 ABA 问题解决方案和 CAS 性能优化策略,并提供了相应的代码示例。
3.2 高性能无锁队列
自定义信号量实现
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
// 自定义信号量类
class CustomSemaphore {
private final Sync sync;
// 构造函数,初始化信号量许可数量
public CustomSemaphore(int permits) {
sync = new Sync(permits);
}
// 获取许可
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
// 释放许可
public void release() {
sync.releaseShared(1);
}
// 内部同步器类,继承自 AQS
private static final 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;
}
}
}
}
}
自定义可重入读写锁实现
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
// 自定义可重入读写锁类
class CustomReadWriteLock {
private final Sync sync = new Sync();
// 获取读锁
public void readLock() {
sync.acquireShared(1);
}
// 释放读锁
public void readUnlock() {
sync.releaseShared(1);
}
// 获取写锁
public void writeLock() {
sync.acquire(1);
}
// 释放写锁
public void writeUnlock() {
sync.release(1);
}
// 内部同步器类,继承自 AQS
private static final class Sync extends AbstractQueuedSynchronizer {
private static final int SHARED_SHIFT = 16;
private static final int SHARED_UNIT = (1 << SHARED_SHIFT);
private static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
private static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
// 获取共享计数
static int sharedCount(int c) {
return c >>> SHARED_SHIFT;
}
// 获取独占计数
static int exclusiveCount(int c) {
return c & EXCLUSIVE_MASK;
}
// 尝试获取共享资源
@Override
protected int tryAcquireShared(int unused) {
Thread current = Thread.currentThread();
int c = getState();
if (exclusiveCount(c) != 0 && getExclusiveOwnerThread() != current) {
return -1;
}
int r = sharedCount(c);
if (!compareAndSetState(c, c + SHARED_UNIT)) {
return -1;
}
if (r == 0) {
setExclusiveOwnerThread(null);
}
return 1;
}
// 尝试释放共享资源
@Override
protected boolean tryReleaseShared(int unused) {
for (;;) {
int c = getState();
int nextc = c - SHARED_UNIT;
if (compareAndSetState(c, nextc)) {
return nextc == 0;
}
}
}
// 尝试获取独占资源
@Override
protected boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);
if (c != 0) {
if (w == 0 || current != getExclusiveOwnerThread()) {
return false;
}
if (w + exclusiveCount(acquires) > MAX_COUNT) {
throw new Error("Maximum lock count exceeded");
}
setState(c + acquires);
return true;
}
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
return false;
}
// 尝试释放独占资源
@Override
protected boolean tryRelease(int releases) {
if (!isHeldExclusively()) {
throw new IllegalMonitorStateException();
}
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
if (free) {
setExclusiveOwnerThread(null);
}
setState(nextc);
return free;
}
// 判断是否为当前线程独占
@Override
protected boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
}
}
测试代码
public class AQSPracticeTest {
public static void main(String[] args) {
// 测试自定义信号量
CustomSemaphore semaphore = new CustomSemaphore(2);
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " acquired permit");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
System.out.println(Thread.currentThread().getName() + " released permit");
}
}).start();
}
// 测试自定义可重入读写锁
CustomReadWriteLock readWriteLock = new CustomReadWriteLock();
for (int i = 0; i < 3; i++) {
new Thread(() -> {
readWriteLock.readLock();
try {
System.out.println(Thread.currentThread().getName() + " acquired read lock");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
readWriteLock.readUnlock();
System.out.println(Thread.currentThread().getName() + " released read lock");
}
}).start();
}
new Thread(() -> {
readWriteLock.writeLock();
try {
System.out.println(Thread.currentThread().getName() + " acquired write lock");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
readWriteLock.writeUnlock();
System.out.println(Thread.currentThread().getName() + " released write lock");
}
}).start();
}
}
代码解释
-
自定义信号量:
CustomSemaphore
类使用Sync
内部类继承自AbstractQueuedSynchronizer
来实现信号量的功能。acquire
方法用于获取许可,release
方法用于释放许可。tryAcquireShared
和tryReleaseShared
方法分别实现了获取和释放共享资源的逻辑。
-
自定义可重入读写锁:
CustomReadWriteLock
类使用Sync
内部类继承自AbstractQueuedSynchronizer
来实现可重入读写锁的功能。readLock
和readUnlock
方法用于获取和释放读锁,writeLock
和writeUnlock
方法用于获取和释放写锁。tryAcquireShared
、tryReleaseShared
、tryAcquire
和tryRelease
方法分别实现了获取和释放共享资源、独占资源的逻辑。
-
测试代码:
- 创建了一个自定义信号量和一个自定义可重入读写锁,并启动多个线程来测试它们的功能。
4.2 常见问题解决方案
场景:高竞争环境下的性能瓶颈
方案:
- 使用LongAdder替代AtomicLong
- 增加锁分离(如ConcurrentHashMap的分段锁)
- 采用无锁数据结构
场景:线程饥饿问题
方案:
// 公平锁实现
public class FairLock extends AbstractQueuedSynchronizer {
protected final boolean tryAcquire(int acquires) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
}
五、架构演进与未来展望
5.1 Java并发模型演进
timeline
title Java并发模型发展史
section JDK1.5
JUC包诞生 : AQS/CAS/Atomic
section JDK1.7
Fork/Join框架 : 工作窃取算法
section JDK1.8
CompletableFuture : 异步编程
StampedLock : 乐观读锁
section JDK19+
虚拟线程 : Project Loom
5.2 新一代并发编程模式
- 反应式编程:Project Reactor
- 协程支持:Virtual Thread
- 无锁算法:RCU(Read-Copy-Update)