Atomic原子类实现原理:CAS机制深度解析
一、CAS 核心思想:乐观锁的硬件实现
1. CAS 操作的本质
java
复制
下载
// CAS 伪代码:比较并交换
public class CASPrinciple {
/*
CAS(Compare And Swap) 操作:
内存位置:V
预期原值:A
新值:B
操作:if (V == A) { V = B; return true; }
else { return false; }
关键特性:
1. 原子性:CPU保证这个操作不可分割
2. 无锁:不需要传统锁机制
3. 乐观:假设没有竞争,失败重试
*/
}
// Java中的CAS方法(Unsafe类提供)
public final class Unsafe {
// 核心CAS方法
public final native boolean compareAndSwapInt(
Object o, long offset,
int expected, int x
);
public final native boolean compareAndSwapLong(
Object o, long offset,
long expected, long x
);
public final native boolean compareAndSwapObject(
Object o, long offset,
Object expected, Object x
);
}
2. CAS 与 传统锁的对比
java
复制
下载
// 传统synchronized vs CAS
public class LockVsCAS {
// 方式1:synchronized(悲观锁)
private int value1;
public synchronized void increment1() {
value1++; // 获取锁 → 执行 → 释放锁
}
// 方式2:CAS(乐观锁)
private volatile int value2;
private static final Unsafe unsafe = getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(LockVsCAS.class.getDeclaredField("value2"));
} catch (Exception ex) { throw new Error(ex); }
}
public void increment2() {
int current, next;
do {
current = unsafe.getIntVolatile(this, valueOffset);
next = current + 1;
} while (!unsafe.compareAndSwapInt(
this, valueOffset, current, next
));
}
/*
性能对比(8线程竞争,1000万次自增):
- synchronized: ~4500ms
- CAS: ~1200ms
- 无竞争时差距更大
*/
}
二、Atomic原子类源码深度解析
1. AtomicInteger 核心实现
java
复制
下载
// AtomicInteger 源码关键部分
public class AtomicInteger extends Number implements java.io.Serializable {
// 1. 关键:volatile保证可见性
private volatile int value;
// 2. 获取Unsafe实例(单例)
private static final Unsafe unsafe = Unsafe.getUnsafe();
// 3. 获取value字段的内存偏移量
private static final long valueOffset;
static {
try {
// 计算value字段在对象内存中的偏移地址
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 4. 核心:原子自增
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
// 5. CAS操作
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
// 6. getAndAddInt实现
public final int getAndAddInt(Object o, long offset, int delta) {
int v;
do {
v = getIntVolatile(o, offset); // 原子读
} while (!compareAndSwapInt(o, offset, v, v + delta)); // CAS重试
return v;
}
}
2. 内存偏移量原理
java
复制
下载
// 对象内存布局与偏移量计算
public class MemoryLayout {
/*
64位JVM(开启压缩指针)对象头:
+----------------------+--------+--------+
| Mark Word (64 bits) | Klass | 数组长度 |
+----------------------+--------+--------+
AtomicInteger实例内存布局:
+----------------------+--------+--------+--------+
| 对象头 (12 bytes) | value | padding| |
+----------------------+--------+--------+--------+
↑ ↑
base address valueOffset
valueOffset计算:
1. 对象头大小:12字节(Mark Word 8 + Klass 4)
2. 对齐填充:可能为0
3. value字段偏移 = 12 + padding
为什么需要偏移量?
- CAS直接操作内存地址,需要知道字段的精确位置
- 偏移量在类加载时计算并缓存,后续直接使用
*/
}
三、CAS 的硬件实现原理
1. CPU 指令级支持
assembly
复制
下载
// x86架构的CAS指令:CMPXCHG
mov eax, expected_value ; 将预期值加载到EAX寄存器
mov ebx, new_value ; 将新值加载到EBX寄存器
lock cmpxchg [memory], ebx ; 原子比较交换
; 指令详解:
; 1. lock前缀:保证总线锁定,防止其他CPU访问内存
; 2. cmpxchg:比较[memory]和EAX的值
; 3. 如果相等:ZF=1,[memory] ← EBX
; 4. 如果不相等:ZF=0,EAX ← [memory]
// ARM架构的CAS指令:LDREX/STREX
LDREX R1, [R0] ; 加载并独占标记
CMP R1, R2 ; 比较
STREXEQ R3, R4, [R0] ; 条件存储
2. 缓存一致性协议(MESI)
java
复制
下载
// CAS 与 CPU缓存的交互
public class MESIProtocol {
/*
MESI协议状态:
- Modified (M):缓存行已被修改,与主存不一致
- Exclusive (E):缓存行独占,与主存一致
- Shared (S):缓存行被多个CPU共享
- Invalid (I):缓存行无效
CAS操作时的缓存状态变化:
初始:CPU1的缓存行状态为E(独占)
1. CPU1执行CAS:
- 检查缓存行状态
- 如果是E/M状态,直接修改缓存
- 如果是S状态,需要升级为E/M
2. 其他CPU的缓存行变为I(无效)
3. CPU1修改完成后,其他CPU需要时重新加载
优势:
- 减少总线锁定的频率
- 提高多核CPU的并发性能
*/
}
3. 内存屏障(Memory Barrier)
java
复制
下载
// CAS操作中的内存屏障
public class MemoryBarrier {
/*
CAS操作隐含的内存屏障:
1. 写屏障(Store Barrier)
- 保证CAS之前的写操作对后续操作可见
- 防止指令重排序
2. 读屏障(Load Barrier)
- 保证CAS之后的读操作能读取最新值
- 防止读取陈旧数据
Unsafe中的显式屏障:
*/
private static final Unsafe unsafe = Unsafe.getUnsafe();
public void barrierOperations() {
unsafe.loadFence(); // 读屏障
unsafe.storeFence(); // 写屏障
unsafe.fullFence(); // 全屏障
// CAS操作自动插入屏障
// compareAndSwapInt()内部会插入必要的屏障
}
}
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc
需要全套面试笔记及答案
【点击此处即可/免费获取】
四、CAS 在各类原子操作中的应用
1. 基本原子类
java
复制
下载
// AtomicInteger的CAS应用
public class AtomicIntegerCAS {
// 1. getAndIncrement(原子自增)
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
// 2. getAndAdd(原子加法)
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
// 3. lazySet(延迟写)
public final void lazySet(int newValue) {
// 不保证立即可见,但有最终可见性
unsafe.putOrderedInt(this, valueOffset, newValue);
}
// 4. weakCompareAndSet(弱化CAS)
public final boolean weakCompareAndSet(int expect, int update) {
// 可能失败,不保证内存顺序
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
}
2. 原子引用类型
java
复制
下载
// AtomicReference 的CAS应用
public class AtomicReference<V> {
private volatile V value;
private static final long valueOffset;
// CAS更新引用
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(
this, valueOffset, expect, update
);
}
// 应用:无锁栈
public class LockFreeStack<E> {
private static class Node<E> {
final E item;
Node<E> next;
Node(E item) { this.item = item; }
}
private final AtomicReference<Node<E>> top =
new AtomicReference<>();
public void push(E item) {
Node<E> newHead = new Node<>(item);
Node<E> oldHead;
do {
oldHead = top.get();
newHead.next = oldHead;
} while (!top.compareAndSet(oldHead, newHead));
}
}
}
3. 原子数组
java
复制
下载
// AtomicIntegerArray 的CAS应用
public class AtomicIntegerArray {
private final int[] array;
// 计算数组元素的内存地址
private long checkedByteOffset(int i) {
if (i < 0 || i >= array.length)
throw new IndexOutOfBoundsException();
return byteOffset(i);
}
private static long byteOffset(int i) {
// 地址 = 数组基地址 + 索引 × 元素大小
return ((long) i << shift) + base;
}
// 原子更新数组元素
public final boolean compareAndSet(int i, int expect, int update) {
return compareAndSetRaw(checkedByteOffset(i), expect, update);
}
private boolean compareAndSetRaw(long offset, int expect, int update) {
return unsafe.compareAndSwapInt(array, offset, expect, update);
}
}
4. 字段更新器
java
复制
下载
// AtomicIntegerFieldUpdater 的CAS应用
public class AtomicIntegerFieldUpdater<T> {
// 场景:大量对象需要原子计数,但不想每个对象都包装AtomicInteger
public class Counter {
volatile int count; // 必须是volatile
}
public void demo() {
AtomicIntegerFieldUpdater<Counter> updater =
AtomicIntegerFieldUpdater.newUpdater(Counter.class, "count");
Counter counter = new Counter();
updater.incrementAndGet(counter); // CAS更新字段
}
// 原理:通过反射获取字段偏移量
private static long fieldOffset(Class<?> tclass, String fieldName) {
Field field = tclass.getDeclaredField(fieldName);
return unsafe.objectFieldOffset(field);
}
}
五、CAS 的三大核心问题与解决方案
1. ABA 问题
java
复制
下载
// ABA问题示例
public class ABAProblem {
private static AtomicInteger atomic = new AtomicInteger(100);
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
// A -> B -> A
atomic.compareAndSet(100, 101); // A->B
atomic.compareAndSet(101, 100); // B->A
});
Thread t2 = new Thread(() -> {
try {
Thread.sleep(100); // 确保t1完成ABA操作
} catch (InterruptedException e) {}
// 以为还是100,其实中间变过
boolean success = atomic.compareAndSet(100, 200);
System.out.println("CAS成功: " + success); // true,但不安全!
});
t1.start(); t2.start();
t1.join(); t2.join();
}
// 解决方案1:AtomicStampedReference(版本号)
public class ABASolution1 {
private AtomicStampedReference<Integer> stampedRef =
new AtomicStampedReference<>(100, 0);
public void update() {
int[] stampHolder = new int[1];
int currentStamp, newStamp;
Integer currentRef, newRef;
do {
currentRef = stampedRef.get(stampHolder);
currentStamp = stampHolder[0];
newRef = currentRef + 10;
newStamp = currentStamp + 1; // 每次更新版本号+1
} while (!stampedRef.compareAndSet(
currentRef, newRef, currentStamp, newStamp
));
}
}
// 解决方案2:AtomicMarkableReference(标记位)
public class ABASolution2 {
private AtomicMarkableReference<Integer> markedRef =
new AtomicMarkableReference<>(100, false);
public void update() {
boolean[] markHolder = new boolean[1];
Integer currentRef, newRef;
boolean currentMark, newMark;
do {
currentRef = markedRef.get(markHolder);
currentMark = markHolder[0];
newRef = currentRef + 10;
newMark = !currentMark; // 切换标记位
} while (!markedRef.compareAndSet(
currentRef, newRef, currentMark, newMark
));
}
}
}
2. 循环时间长开销大
java
复制
下载
// CAS自旋开销问题
public class CASSpinCost {
// 高竞争场景下的CAS问题
public void highContentionProblem() {
AtomicInteger counter = new AtomicInteger(0);
// 100个线程同时CAS
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 100; i++) {
executor.submit(() -> {
for (int j = 0; j < 10000; j++) {
int current, next;
do {
current = counter.get();
next = current + 1;
} while (!counter.compareAndSet(current, next));
// 高竞争下大量CAS失败重试,CPU空转
}
});
}
}
// 解决方案1:退避策略
public class BackoffStrategy {
public boolean casWithBackoff(AtomicInteger atomic,
int expect, int update) {
int retries = 0;
final int maxRetries = 10;
while (!atomic.compareAndSet(expect, update)) {
if (++retries > maxRetries) {
return false;
}
// 指数退避
try {
Thread.sleep((long) Math.pow(2, retries));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
expect = atomic.get(); // 重新获取最新值
}
return true;
}
}
// 解决方案2:LongAdder(分段CAS)
public class LongAdderSolution {
/*
LongAdder原理:
- 多个Cell数组分段计数
- 线程哈希到不同Cell减少竞争
- 最终求和时合并所有Cell
性能对比(16线程,1亿次自增):
- AtomicLong: ~4500ms
- LongAdder: ~800ms
*/
private LongAdder adder = new LongAdder();
public void increment() {
adder.increment(); // 内部使用分段CAS
}
public long sum() {
return adder.sum(); // 合并所有分段
}
}
}
3. 只能保证一个共享变量的原子操作
java
复制
下载
// 多变量原子操作问题
public class MultiVariableCAS {
// 问题:无法原子地同时更新两个变量
public class Account {
private AtomicInteger balance = new AtomicInteger(100);
private AtomicInteger version = new AtomicInteger(0);
public void transfer(int amount) {
// ❌ 这不是原子操作!
balance.addAndGet(amount);
version.incrementAndGet();
}
}
// 解决方案1:使用AtomicReference包装多个变量
public class AccountSolution1 {
private static class AccountState {
final int balance;
final int version;
AccountState(int balance, int version) {
this.balance = balance;
this.version = version;
}
}
private AtomicReference<AccountState> state =
new AtomicReference<>(new AccountState(100, 0));
public void transfer(int amount) {
AccountState current, next;
do {
current = state.get();
next = new AccountState(
current.balance + amount,
current.version + 1
);
} while (!state.compareAndSet(current, next));
}
}
// 解决方案2:使用锁(必要时)
public class AccountSolution2 {
private int balance = 100;
private int version = 0;
private final Object lock = new Object();
public void transfer(int amount) {
synchronized (lock) {
balance += amount;
version++;
}
}
}
// 解决方案3:使用VarHandle(JDK9+)
public class AccountSolution3 {
private volatile int balance = 100;
private volatile int version = 0;
private static final VarHandle BALANCE_HANDLE;
private static final VarHandle VERSION_HANDLE;
static {
try {
var lookup = MethodHandles.lookup();
BALANCE_HANDLE = lookup.findVarHandle(
AccountSolution3.class, "balance", int.class);
VERSION_HANDLE = lookup.findVarHandle(
AccountSolution3.class, "version", int.class);
} catch (Exception e) { throw new Error(e); }
}
public void transfer(int amount) {
// 仍然不是原子操作,但提供了更强的内存语义
BALANCE_HANDLE.getAndAdd(this, amount);
VERSION_HANDLE.getAndAdd(this, 1);
}
}
}
六、CAS 性能优化策略
1. 缓存行填充(False Sharing 防范)
java
复制
下载
// 伪共享问题与解决方案
public class FalseSharing {
// 问题:两个volatile变量在同一缓存行
public class ProblemExample {
volatile long value1; // 与value2可能在同一缓存行
volatile long value2;
// 线程1写value1,线程2写value2
// 会互相使对方缓存行无效,性能下降
}
// 解决方案:缓存行填充
public class PaddedAtomicLong extends AtomicLong {
// 一个缓存行通常64字节,填充至至少64字节
private long p1, p2, p3, p4, p5, p6, p7 = 0L;
public PaddedAtomicLong(long initialValue) {
super(initialValue);
}
// Java 8+:使用@Contended注解(需开启-XX:-RestrictContended)
@jdk.internal.vm.annotation.Contended
private volatile long contendedValue;
}
// 实际应用:LongAdder的Cell类
static final class Cell {
volatile long value;
// 使用@Contended避免伪共享
@jdk.internal.vm.annotation.Contended
Cell(long x) { value = x; }
}
}
2. CAS 操作批量化
java
复制
下载
// 批量CAS减少竞争
public class BatchCAS {
// 传统方式:多次CAS
public void traditionalWay(AtomicIntegerArray array) {
for (int i = 0; i < array.length(); i++) {
array.compareAndSet(i, 0, 1); // 每次都是独立的CAS
}
}
// 批处理方式:减少CAS次数
public void batchWay(AtomicIntegerArray array) {
// 先检查是否需要更新
boolean needUpdate = false;
for (int i = 0; i < array.length(); i++) {
if (array.get(i) == 0) {
needUpdate = true;
break;
}
}
if (needUpdate) {
// 批量更新
for (int i = 0; i < array.length(); i++) {
array.compareAndSet(i, 0, 1);
}
}
}
// 使用VarHandle批量操作
public class BatchUpdateWithVarHandle {
private static final VarHandle ARRAY_HANDLE;
private final int[] array;
public void batchCompareAndSet(int[] expected, int[] updates) {
// 可以使用VarHandle.compareAndExchange批量操作
// (简化示例,实际需要更复杂实现)
}
}
}
3. 自适应自旋优化
java
复制
下载
// JVM的自适应自旋优化
public class AdaptiveSpinning {
/*
JVM对CAS的自适应优化:
1. 自旋次数动态调整:
- 上次CAS成功 → 增加自旋次数
- 上次CAS失败 → 减少自旋次数
2. 自旋策略:
- 固定次数自旋(默认10次)
- 自适应自旋(根据历史成功率)
- 可能直接挂起线程
3. 相关JVM参数:
-XX:+UseSpinning 启用自旋
-XX:PreBlockSpin=10 默认自旋次数
-XX:+UseAdaptiveSpinning 启用自适应自旋
*/
// HotSpot源码中的自适应逻辑(简化)
public class AdaptiveSelf {
private int spinCount = 10; // 初始自旋次数
public boolean adaptiveCAS(AtomicInteger atomic,
int expect, int update) {
int currentSpin = spinCount;
for (int i = 0; i < currentSpin; i++) {
if (atomic.compareAndSet(expect, update)) {
// 成功,增加自旋次数(上限100)
spinCount = Math.min(100, spinCount + 2);
return true;
}
}
// 失败,减少自旋次数(下限1)
spinCount = Math.max(1, spinCount / 2);
return atomic.compareAndSet(expect, update);
}
}
}
七、现代JVM中的CAS增强
1. VarHandle(JDK9+ 的更优选择)
java
复制
下载
// VarHandle 替代 Unsafe
public class VarHandleCAS {
private volatile int value;
private static final VarHandle VALUE_HANDLE;
static {
try {
VALUE_HANDLE = MethodHandles
.lookup()
.findVarHandle(VarHandleCAS.class, "value", int.class);
} catch (Exception e) { throw new Error(e); }
}
// 基本CAS操作
public boolean compareAndSet(int expected, int update) {
return VALUE_HANDLE.compareAndSet(this, expected, update);
}
// 更丰富的原子操作
public void advancedOperations() {
// 原子加法
VALUE_HANDLE.getAndAdd(this, 10);
// 原子比较交换(强内存语义)
VALUE_HANDLE.compareAndExchange(this, 100, 200);
// 原子获取并设置
VALUE_HANDLE.getAndSet(this, 300);
// 弱原子操作(可能失败)
VALUE_HANDLE.weakCompareAndSetPlain(this, 300, 400);
}
// 内存顺序控制
public void memoryOrdering() {
// 获取(强内存顺序)
VALUE_HANDLE.getAcquire(this);
// 设置(强内存顺序)
VALUE_HANDLE.setRelease(this, 500);
// 宽松内存顺序
VALUE_HANDLE.getOpaque(this);
VALUE_HANDLE.setOpaque(this, 600);
}
}
2. JDK12 的 Atomic增强
java
复制
下载
// JDK12+ 的Atomic增强特性
public class JDK12AtomicFeatures {
// 1. 带描述符的异常信息
public void exceptionWithDescription() {
AtomicInteger atomic = new AtomicInteger();
// 旧方式:简单的false
boolean success = atomic.compareAndSet(1, 2);
// 新方式:可以获取更多信息
// (API示例,实际可能有所不同)
}
// 2. 增强的accumulate方法
public void accumulateOperations() {
AtomicInteger atomic = new AtomicInteger(10);
// 累积操作
atomic.accumulateAndGet(5, (x, y) -> x * y); // 10 * 5 = 50
// 更复杂的函数式操作
atomic.getAndUpdate(x -> x * x + 1);
}
}
3. 针对特定CPU架构的优化
java
复制
下载
// 不同CPU架构的CAS优化
public class CPUOptimizedCAS {
/*
x86架构:
- 原生的CMPXCHG指令
- lock前缀保证原子性
- 强大的内存模型
ARM架构:
- LDREX/STREX指令对
- 需要显示的内存屏障
- 内存模型较弱
PowerPC架构:
- lwarx/stwcx指令对
- 需要处理复杂的内存顺序
JVM的运行时优化:
1. 根据CPU架构选择最优的CAS实现
2. 动态生成机器码(JIT优化)
3. 内联热点CAS操作
*/
// HotSpot的架构特定实现
public class PlatformDependentCAS {
// x86实现
static final class X86CAS {
// 使用lock cmpxchg指令
}
// ARM实现
static final class ARMCAS {
// 使用ldrex/strex指令对
// 需要dmb/isb内存屏障
}
// AArch64实现
static final class AArch64CAS {
// 使用ldxr/stxr指令对
// 需要dmb内存屏障
}
}
}
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc
需要全套面试笔记及答案
【点击此处即可/免费获取】
八、CAS 在生产环境的最佳实践
1. 监控与诊断
java
复制
下载
// CAS性能监控
public class CASMonitor {
// 监控CAS成功率
public class CASSuccessRateMonitor {
private final AtomicLong attempts = new AtomicLong();
private final AtomicLong successes = new AtomicLong();
public boolean monitoredCAS(AtomicInteger atomic,
int expect, int update) {
attempts.incrementAndGet();
boolean success = atomic.compareAndSet(expect, update);
if (success) {
successes.incrementAndGet();
}
return success;
}
public double getSuccessRate() {
long a = attempts.get();
long s = successes.get();
return a == 0 ? 0 : (double) s / a;
}
}
// JFR(Java Flight Recorder)事件
public class CASJFREvents {
/*
JFR可以监控:
1. CAS操作次数
2. CAS失败率
3. 自旋等待时间
4. 缓存一致性流量
启用JFR:
-XX:+FlightRecorder
-XX:StartFlightRecording=filename=recording.jfr
*/
}
}
// 诊断工具使用
public class CASDiagnostics {
/*
常用诊断命令:
1. 查看CAS相关JVM参数
jcmd <pid> VM.flags | grep -i spin
2. 查看竞争情况
jstack <pid> | grep -A5 -B5 "parking"
3. 性能分析
perf stat -e cache-misses,cache-references java App
4. JMH基准测试
@Benchmark
@BenchmarkMode(Mode.Throughput)
public void testCAS(Blackhole bh) {
atomic.incrementAndGet();
}
*/
}
2. 配置优化建议
bash
复制
下载
# JVM参数优化建议
# CAS相关优化
-XX:+UseSpinning # 启用自旋锁
-XX:PreBlockSpin=15 # 自旋次数(默认10)
-XX:+UseAdaptiveSpinning # 自适应自旋
-XX:+UseBiasedLocking # 偏向锁(减少CAS竞争)
-XX:BiasedLockingStartupDelay=0 # 立即启用偏向锁
# 内存屏障优化
-XX:+UseBarriersForVolatile # volatile使用内存屏障
-XX:+UseCondCardMark # 条件卡片标记
# 线程本地分配缓冲(TLAB)
-XX:+UseTLAB # 启用TLAB
-XX:TLABSize # TLAB大小
-XX:+ResizeTLAB # 动态调整TLAB
# CPU亲和性(降低缓存一致性开销)
-XX:+UseNUMA # NUMA感知
-XX:+UseBoundThreads # 绑定线程到CPU核心
3. 编码最佳实践
java
复制
下载
// CAS使用的最佳实践
public class CASBestPractices {
// 实践1:避免在热点路径上使用CAS
public void avoidCASInHotPath() {
// ❌ 错误:高频调用路径中使用CAS
// ✅ 正确:使用局部变量累积,批量CAS
AtomicInteger counter = new AtomicInteger();
ThreadLocal<Integer> localCounter = ThreadLocal.withInitial(() -> 0);
// 每个线程本地计数
localCounter.set(localCounter.get() + 1);
// 定期同步到全局计数器
if (shouldSync()) {
counter.addAndGet(localCounter.get());
localCounter.set(0);
}
}
// 实践2:使用合适的原子类
public void chooseRightAtomicClass() {
// 单计数器 → AtomicLong
// 高并发计数器 → LongAdder
// 对象引用 → AtomicReference
// 数组元素 → AtomicIntegerArray
// 字段更新 → AtomicIntegerFieldUpdater
}
// 实践3:CAS失败处理策略
public class CASFailureHandling {
public boolean safeCAS(AtomicInteger atomic,
int expect, int update,
int maxRetries) {
int retries = 0;
do {
if (atomic.compareAndSet(expect, update)) {
return true;
}
// 重试前可以做一些优化
Thread.onSpinWait(); // JDK9+ 的提示性等待
retries++;
} while (retries < maxRetries);
// 失败后的降级策略
return fallbackStrategy(atomic, expect, update);
}
private boolean fallbackStrategy(AtomicInteger atomic,
int expect, int update) {
// 方案1:使用锁
synchronized (this) {
if (atomic.get() == expect) {
atomic.set(update);
return true;
}
return false;
}
// 方案2:记录日志,返回false
// 方案3:抛异常让上层处理
}
}
}
总结:CAS是现代并发编程的基石,理解其硬件实现、内存模型和优化策略对于编写高性能并发程序至关重要。在实际应用中,要根据具体场景选择合适的原子类和优化策略,并建立完善的监控体系。记住:CAS不是银弹,在高竞争场景下可能需要结合其他同步机制。