2026/4/16 8:25:11
网站建设
项目流程
做企业网站的合同,婚纱摄影网站开发的目的,网页制作作业网站,网站转微信小程序Atomic原子类实现原理#xff1a;CAS机制深度解析
一、CAS 核心思想#xff1a;乐观锁的硬件实现
1. CAS 操作的本质
java 复制 下载
// CAS 伪代码#xff1a;比较并交换
public class CASPrinciple {/*CAS(Compare And Swap) 操作#xff1a;内存位置#xff1a;V预…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 { // 方式1synchronized悲观锁 private int value1; public synchronized void increment1() { value1; // 获取锁 → 执行 → 释放锁 } // 方式2CAS乐观锁 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. 如果相等ZF1[memory] ← EBX ; 4. 如果不相等ZF0EAX ← [memory] // ARM架构的CAS指令LDREX/STREX LDREX R1, [R0] ; 加载并独占标记 CMP R1, R2 ; 比较 STREXEQ R3, R4, [R0] ; 条件存储2. 缓存一致性协议MESIjava复制下载// 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 Barrierjava复制下载// 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 AtomicReferenceV { 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 LockFreeStackE { private static class NodeE { final E item; NodeE next; Node(E item) { this.item item; } } private final AtomicReferenceNodeE top new AtomicReference(); public void push(E item) { NodeE newHead new Node(item); NodeE 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 AtomicIntegerFieldUpdaterT { // 场景大量对象需要原子计数但不想每个对象都包装AtomicInteger public class Counter { volatile int count; // 必须是volatile } public void demo() { AtomicIntegerFieldUpdaterCounter 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(); } // 解决方案1AtomicStampedReference版本号 public class ABASolution1 { private AtomicStampedReferenceInteger 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 )); } } // 解决方案2AtomicMarkableReference标记位 public class ABASolution2 { private AtomicMarkableReferenceInteger 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; } } // 解决方案2LongAdder分段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 AtomicReferenceAccountState 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使用VarHandleJDK9 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:PreBlockSpin10 默认自旋次数 -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. VarHandleJDK9 的更优选择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; } } // JFRJava Flight Recorder事件 public class CASJFREvents { /* JFR可以监控 1. CAS操作次数 2. CAS失败率 3. 自旋等待时间 4. 缓存一致性流量 启用JFR -XX:FlightRecorder -XX:StartFlightRecordingfilenamerecording.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:PreBlockSpin15 # 自旋次数默认10 -XX:UseAdaptiveSpinning # 自适应自旋 -XX:UseBiasedLocking # 偏向锁减少CAS竞争 -XX:BiasedLockingStartupDelay0 # 立即启用偏向锁 # 内存屏障优化 -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(); ThreadLocalInteger 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 } // 实践3CAS失败处理策略 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不是银弹在高竞争场景下可能需要结合其他同步机制。