2026/4/18 4:29:05
网站建设
项目流程
公众号开发网站,关键词优化易下拉稳定,wordpress调用tag标签,商城图片文章目录1. 核心原理#xff1a;CAS (Compare-And-Swap)什么是 CASJava 中的 Unsafe 类2. 原子类家族谱系3. 实战演练#xff1a;AtomicInteger场景#xff1a;多线程计数器错误示范#xff1a;普通 int正确示范#xff1a;AtomicInteger源码剖析#xff1a;getAndIncrem…文章目录1. 核心原理CAS (Compare-And-Swap)什么是 CASJava 中的 Unsafe 类2. 原子类家族谱系3. 实战演练AtomicInteger场景多线程计数器错误示范普通 int正确示范AtomicInteger源码剖析getAndIncrement5. 高性能利器LongAdder (JDK 8)设计思想分段锁空间换时间AtomicLong vs LongAdder 性能对比示意代码示例在多线程并发编程的浩瀚宇宙中线程安全始终是核心议题。当我们需要对一个变量进行简单的累加操作时volatile关键字虽然能保证可见性却无法保证原子性而synchronized锁虽然强大但在高并发场景下往往伴随着沉重的上下文切换开销。这时Java原子类Atomic Classes应运而生。它们位于java.util.concurrent.atomic包下利用底层硬件的 CAS 机制以一种无锁Lock-Free的高效方式解决了并发场景下的原子性问题。1. 核心原理CAS (Compare-And-Swap)原子类的魔法源自于CAS。它是一条 CPU 并发原语。什么是 CAS关于CAS的原理可以看这篇https://blog.csdn.net/Tracycoder/article/details/156860586?spm1011.2415.3001.10575sharefrommp_manage_linkJava 中的 Unsafe 类Java 无法直接访问底层操作系统而是通过sun.misc.Unsafe类来操作内存。原子类内部正是调用了 Unsafe 的compareAndSwap系列方法。2. 原子类家族谱系JDK 提供了丰富的原子类主要可以分为以下四类分类包含类描述基本类型AtomicInteger,AtomicLong,AtomicBoolean直接更新基本类型数据。数组类型AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray原子更新数组中的某个元素。引用类型AtomicReference,AtomicStampedReference,AtomicMarkableReference原子更新对象引用解决ABA问题。对象属性AtomicIntegerFieldUpdater,AtomicLongFieldUpdater,AtomicReferenceFieldUpdater原子更新对象的某个字段。3. 实战演练AtomicIntegerAtomicInteger是最常用的原子类。让我们对比一下使用int和AtomicInteger在多线程下的表现。场景多线程计数器假设有 100 个线程每个线程对计数器累加 1000 次。错误示范普通 intpublicclassUnsafeCounter{privatestaticintcount0;publicstaticvoidmain(String[]args)throwsInterruptedException{Thread[]threadsnewThread[100];for(inti0;i100;i){threads[i]newThread(()-{for(intj0;j1000;j){count;// 非原子操作读 - 改 - 写}});threads[i].start();}for(Threadt:threads)t.join();// 预期结果100000实际结果通常小于 100000System.out.println(Final Count (Unsafe): count);}}正确示范AtomicIntegerimportjava.util.concurrent.atomic.AtomicInteger;publicclassSafeCounter{// 使用原子类privatestaticAtomicIntegeratomicCountnewAtomicInteger(0);publicstaticvoidmain(String[]args)throwsInterruptedException{Thread[]threadsnewThread[100];for(inti0;i100;i){threads[i]newThread(()-{for(intj0;j1000;j){// 相当于 i但在硬件层面保证原子性atomicCount.getAndIncrement();}});threads[i].start();}for(Threadt:threads)t.join();// 结果始终为 100000System.out.println(Final Count (Atomic): atomicCount.get());}}源码剖析getAndIncrementAtomicInteger的getAndIncrement是如何实现的// JDK 8 源码片段publicfinalintgetAndIncrement(){// this: 当前对象// valueOffset: value 字段在内存中的偏移量// 1: 增加的值returnunsafe.getAndAddInt(this,valueOffset,1);}// Unsafe 类中的实现 (模拟)publicfinalintgetAndAddInt(Objecto,longoffset,intdelta){intv;do{// 1. 获取内存中当前的值vgetIntVolatile(o,offset);// 2. 循环尝试 CAS 操作// 如果内存值还是 v则更新为 v delta返回 true 退出循环// 否则说明被其他线程改了返回 false继续循环自旋}while(!compareAndSwapInt(o,offset,v,vdelta));returnv;}5. 高性能利器LongAdder (JDK 8)虽然AtomicLong使用 CAS 保证了原子性但在超高并发下大量线程同时竞争更新同一个变量会导致大量 CAS 失败并自旋消耗 CPU 资源。JDK 8 引入了LongAdder。设计思想分段锁空间换时间LongAdder内部维护了一个base变量和一个Cell[]数组。无竞争时直接更新base。有竞争时线程被哈希映射到Cell数组的某个槽位对该槽位的值进行 CAS 更新。获取最终结果时sum base sum(Cell[])。AtomicLong vs LongAdder 性能对比示意LongAdderCASHashHashHashThread ABaseThread BCell 1Thread CCell 2Thread DAtomicLongCAS 竞争CAS 竞争CAS 竞争CAS 竞争Thread 1ValueThread 2Thread 3Thread 4代码示例importjava.util.concurrent.atomic.LongAdder;publicclassLongAdderDemo{publicstaticvoidmain(String[]args){LongAdderaddernewLongAdder();// 多个线程同时累加adder.increment();adder.add(10);// 获取总和System.out.println(Sum: adder.sum());}}注意LongAdder的sum()方法返回的值只是一个近似准确值在并发极高时统计过程中可能有新的累加发生但在统计计数等场景下完全够用且性能极佳。