2026/1/2 18:18:58
网站建设
项目流程
郑州驾校网站建设,百度推广官网首页,动漫制作技术和动漫设计,wordpress 后台 404一、为什么需要原子操作类#xff1f;1.1 问题的由来想象一下这样的场景#xff1a;多个线程同时操作同一个银行账户进行取款#xff0c;如果不加控制#xff0c;可能会出现什么情况#xff1f;// 不安全的计数器示例class UnsafeCounter {private int count 0;public vo…一、为什么需要原子操作类1.1 问题的由来想象一下这样的场景多个线程同时操作同一个银行账户进行取款如果不加控制可能会出现什么情况// 不安全的计数器示例class UnsafeCounter {private int count 0;public void increment() {count; // 这不是原子操作}}count看似简单实际上包含三个步骤读取count的当前值将值加1将新值写回count在多线程环境下这两个步骤可能被其他线程打断导致数据不一致。1.2 传统的解决方案及其缺点传统做法是使用synchronized关键字class SynchronizedCounter {private int count 0;public synchronized void increment() {count;}}synchronized确实能保证线程安全但存在以下问题性能开销锁的获取和释放需要代价可能死锁不正确的锁顺序可能导致死锁降低并发性同一时刻只有一个线程能访问1.3 原子操作类的优势原子操作类基于CASCompare-And-Swap 机制提供了无锁编程避免传统锁的开销高性能在低竞争环境下性能优异无死锁风险基于硬件指令不会产生死锁高并发支持多个线程同时操作二、原子更新基本类型类2.1 AtomicBoolean - 原子更新布尔类型使用场景状态标志位、开关控制、条件判断核心API详解方法 参数 返回值 说明get() - boolean 获取当前值set(boolean newValue) newValue: 新值 void 设置新值getAndSet(boolean newValue) newValue: 新值 boolean 原子性地设置为新值并返回旧值compareAndSet(boolean expect, boolean update) expect: 期望值update: 更新值 boolean 如果当前值等于期望值则原子性地更新lazySet(boolean newValue) newValue: 新值 void 最终设置为新值但不保证立即可见性weakCompareAndSet(boolean expect, boolean update) expect: 期望值update: 更新值 boolean 可能更弱的CAS操作在某些平台上性能更好import java.util.concurrent.atomic.AtomicBoolean;/*** AtomicBoolean示例用于原子性地更新布尔值* 典型场景系统开关、状态标志等*/public class AtomicBooleanDemo {public static void main(String[] args) {// 创建AtomicBoolean初始值为falseAtomicBoolean atomicBoolean new AtomicBoolean(false);// get(): 获取当前值System.out.println(初始值: atomicBoolean.get());// getAndSet(): 原子性地设置为true返回旧值boolean oldValue atomicBoolean.getAndSet(true);System.out.println(getAndSet旧值: oldValue , 新值: atomicBoolean.get());// compareAndSet(): 比较并设置boolean success atomicBoolean.compareAndSet(true, false);System.out.println(CAS操作结果: success , 当前值: atomicBoolean.get());// lazySet(): 最终会设置但不保证立即可见性atomicBoolean.lazySet(true);System.out.println(lazySet后的值: atomicBoolean.get());// weakCompareAndSet(): 弱版本CASboolean weakSuccess atomicBoolean.weakCompareAndSet(true, false);System.out.println(弱CAS操作结果: weakSuccess , 当前值: atomicBoolean.get());}}原理分析AtomicBoolean内部实际上使用int类型来存储0表示false1表示true。通过compareAndSwapInt来实现原子操作。2.2 AtomicInteger - 原子更新整型使用场景计数器、序列号生成、资源数量控制核心API详解方法 参数 返回值 说明get() - int 获取当前值set(int newValue) newValue: 新值 void 设置新值getAndSet(int newValue) newValue: 新值 int 原子性地设置为新值并返回旧值compareAndSet(int expect, int update) expect: 期望值update: 更新值 boolean CAS操作getAndIncrement() - int 原子递增返回旧值getAndDecrement() - int 原子递减返回旧值getAndAdd(int delta) delta: 增量 int 原子加法返回旧值incrementAndGet() - int 原子递增返回新值decrementAndGet() - int 原子递减返回新值addAndGet(int delta) delta: 增量 int 原子加法返回新值updateAndGet(IntUnaryOperator) operator: 更新函数 int 函数式更新accumulateAndGet(int x, IntBinaryOperator) x: 参数operator: 操作函数 int 累积计算import java.util.concurrent.atomic.AtomicInteger;/*** AtomicInteger是最常用的原子类之一* 适用于计数器、ID生成器等需要原子递增的场景*/public class AtomicIntegerDemo {public static void main(String[] args) {AtomicInteger atomicInt new AtomicInteger(0);// 基础操作System.out.println(初始值: atomicInt.get());atomicInt.set(5);System.out.println(set(5)后: atomicInt.get());// 原子递增并返回旧值 - 常用于计数System.out.println(getAndIncrement: atomicInt.getAndIncrement()); // 返回5System.out.println(当前值: atomicInt.get()); // 6// 原子递减并返回旧值System.out.println(getAndDecrement: atomicInt.getAndDecrement()); // 返回6System.out.println(当前值: atomicInt.get()); // 5// 原子加法并返回旧值System.out.println(getAndAdd(10): atomicInt.getAndAdd(10)); // 返回5System.out.println(当前值: atomicInt.get()); // 15// 原子递增并返回新值System.out.println(incrementAndGet: atomicInt.incrementAndGet()); // 16// 原子加法并返回结果 - 适合批量增加int result atomicInt.addAndGet(10);System.out.println(addAndGet(10)结果: result); // 26// 比较并设置 - 核心CAS操作boolean updated atomicInt.compareAndSet(26, 30);System.out.println(CAS操作结果: updated , 当前值: atomicInt.get());// 获取并设置新值 - 适合重置操作int previous atomicInt.getAndSet(40);System.out.println(getAndSet旧值: previous , 新值: atomicInt.get());// JDK8新增函数式更新 - 更灵活的更新方式atomicInt.updateAndGet(x - x * 2);System.out.println(updateAndGet(*2)后的值: atomicInt.get()); // 80// 累积计算atomicInt.accumulateAndGet(10, (x, y) - x y * 2);System.out.println(accumulateAndGet后的值: atomicInt.get()); // 100}}源码分析public final int getAndIncrement() {// 自旋CAS循环直到成功for (;;) {int current get(); // 步骤1获取当前值int next current 1; // 步骤2计算新值if (compareAndSet(current, next)) // 步骤3CAS更新return current; // 成功则返回旧值}// 如果CAS失败说明有其他线程修改了值循环重试}2.3 AtomicLong - 原子更新长整型使用场景大数值计数器、统计信息、唯一ID生成核心API详解方法 参数 返回值 说明get() - long 获取当前值set(long newValue) newValue: 新值 void 设置新值getAndSet(long newValue) newValue: 新值 long 原子性地设置为新值并返回旧值compareAndSet(long expect, long update) expect: 期望值update: 更新值 boolean CAS操作getAndIncrement() - long 原子递增返回旧值getAndDecrement() - long 原子递减返回旧值getAndAdd(long delta) delta: 增量 long 原子加法返回旧值incrementAndGet() - long 原子递增返回新值decrementAndGet() - long 原子递减返回新值addAndGet(long delta) delta: 增量 long 原子加法返回新值updateAndGet(LongUnaryOperator) operator: 更新函数 long 函数式更新accumulateAndGet(long x, LongBinaryOperator) x: 参数operator: 操作函数 long 累积计算import java.util.concurrent.atomic.AtomicLong;/*** AtomicLong用于长整型的原子操作* 在64位系统中性能与AtomicInteger相当*/public class AtomicLongDemo {public static void main(String[] args) {AtomicLong atomicLong new AtomicLong(100L);System.out.println(初始值: atomicLong.get());// 原子递增并返回旧值 - 适合序列号生成System.out.println(getAndIncrement: atomicLong.getAndIncrement());System.out.println(当前值: atomicLong.get());// 原子递减并返回旧值System.out.println(getAndDecrement: atomicLong.getAndDecrement());System.out.println(当前值: atomicLong.get());// 原子加法并返回旧值System.out.println(getAndAdd(50): atomicLong.getAndAdd(50L));System.out.println(当前值: atomicLong.get());// 原子递增并返回新值System.out.println(incrementAndGet: atomicLong.incrementAndGet());// 原子加法并返回结果 - 适合统计累加long newValue atomicLong.addAndGet(50L);System.out.println(addAndGet(50)结果: newValue);// 比较并设置boolean success atomicLong.compareAndSet(250L, 300L);System.out.println(CAS操作结果: success , 当前值: atomicLong.get());// JDK8新增函数式更新atomicLong.updateAndGet(x - x / 2);System.out.println(updateAndGet(/2)后的值: atomicLong.get());// JDK8新增累积计算 - 适合复杂的原子计算atomicLong.accumulateAndGet(100L, (x, y) - x * y);System.out.println(accumulateAndGet后的值: atomicLong.get());}}性能提示在32位系统上AtomicLong的CAS操作可能需要锁住总线性能相对较差。Java 8提供了LongAdder作为高性能替代方案。三、原子更新数组类3.1 AtomicIntegerArray - 原子更新整型数组使用场景并发计数器数组、桶统计、并行计算核心API详解方法 参数 返回值 说明length() - int 返回数组长度get(int i) i: 索引 int 获取指定索引的值set(int i, int newValue) i: 索引newValue: 新值 void 设置指定索引的值getAndSet(int i, int newValue) i: 索引newValue: 新值 int 原子设置并返回旧值compareAndSet(int i, int expect, int update) i: 索引expect: 期望值update: 更新值 boolean 对指定索引进行CAS操作getAndIncrement(int i) i: 索引 int 原子递增指定索引返回旧值getAndDecrement(int i) i: 索引 int 原子递减指定索引返回旧值getAndAdd(int i, int delta) i: 索引delta: 增量 int 原子加法返回旧值incrementAndGet(int i) i: 索引 int 原子递增指定索引返回新值addAndGet(int i, int delta) i: 索引delta: 增量 int 原子加法返回新值import java.util.concurrent.atomic.AtomicIntegerArray;/*** AtomicIntegerArray允许原子地更新数组中的单个元素* 注意构造函数会复制传入的数组不影响原数组*/public class AtomicIntegerArrayDemo {public static void main(String[] args) {int[] initialArray {1, 2, 3, 4, 5};// 创建原子整型数组会复制传入的数组AtomicIntegerArray atomicArray new AtomicIntegerArray(initialArray);System.out.println(数组长度: atomicArray.length());System.out.println(原始数组: atomicArray.toString());// get(): 获取指定索引的值System.out.println(索引0的值: atomicArray.get(0));// set(): 设置指定索引的值atomicArray.set(0, 10);System.out.println(set(0, 10)后的数组: atomicArray.toString());// getAndSet(): 原子更新指定索引的元素并返回旧值int oldValue atomicArray.getAndSet(1, 20);System.out.println(索引1替换前的值: oldValue , 数组: atomicArray.toString());// getAndIncrement(): 原子递增指定索引的元素 - 适合分桶计数oldValue atomicArray.getAndIncrement(2);System.out.println(索引2递增前值: oldValue , 数组: atomicArray.toString());// compareAndSet(): 比较并设置特定位置的元素boolean updated atomicArray.compareAndSet(3, 4, 40);System.out.println(索引3 CAS结果: updated , 数组: atomicArray.toString());// addAndGet(): 原子加法 - 适合累加统计int newValue atomicArray.addAndGet(4, 5);System.out.println(索引4加5后的值: newValue , 数组: atomicArray.toString());// incrementAndGet(): 原子递增并返回新值newValue atomicArray.incrementAndGet(0);System.out.println(索引0递增后的值: newValue);// 重要原始数组不会被修改System.out.println(原始数组值未被修改: initialArray[0]); // 仍然是1}}设计思想AtomicIntegerArray通过复制数组来避免外部修改每个数组元素的更新都是独立的原子操作。3.2 AtomicLongArray - 原子更新长整型数组使用场景大数据统计、时间戳数组、大数值桶统计核心API详解方法 参数 返回值 说明length() - int 返回数组长度get(int i) i: 索引 long 获取指定索引的值set(int i, long newValue) i: 索引newValue: 新值 void 设置指定索引的值getAndSet(int i, long newValue) i: 索引newValue: 新值 long 原子设置并返回旧值compareAndSet(int i, long expect, long update) i: 索引expect: 期望值update: 更新值 boolean 对指定索引进行CAS操作getAndAdd(int i, long delta) i: 索引delta: 增量 long 原子加法返回旧值addAndGet(int i, long delta) i: 索引delta: 增量 long 原子加法返回新值import java.util.concurrent.atomic.AtomicLongArray;/*** AtomicLongArray提供长整型数组的原子操作* 适用于需要大数值范围的并发统计*/public class AtomicLongArrayDemo {public static void main(String[] args) {long[] initialArray {100L, 200L, 300L, 400L, 500L};AtomicLongArray atomicLongArray new AtomicLongArray(initialArray);System.out.println(数组长度: atomicLongArray.length());System.out.println(初始数组: atomicLongArray.toString());// 基础操作System.out.println(索引0的值: atomicLongArray.get(0));atomicLongArray.set(0, 150L);System.out.println(set(0, 150)后的数组: atomicLongArray.toString());// 原子更新操作long oldValue atomicLongArray.getAndSet(1, 250L);System.out.println(索引1替换前的值: oldValue , 数组: atomicLongArray.toString());// 原子加法操作atomicLongArray.getAndAdd(2, 100L);System.out.println(索引2加100后的数组: atomicLongArray.toString());// 比较并设置atomicLongArray.compareAndSet(3, 400L, 450L);System.out.println(索引3 CAS后的数组: atomicLongArray.toString());// 加法并获取新值long newValue atomicLongArray.addAndGet(4, 200L);System.out.println(索引4加200后的值: newValue);}}3.3 AtomicReferenceArray - 原子更新引用类型数组使用场景对象池、缓存数组、并发数据结构核心API详解方法 参数 返回值 说明length() - int 返回数组长度get(int i) i: 索引 E 获取指定索引的引用set(int i, E newValue) i: 索引newValue: 新引用 void 设置指定索引的引用getAndSet(int i, E newValue) i: 索引newValue: 新引用 E 原子设置并返回旧引用compareAndSet(int i, E expect, E update) i: 索引expect: 期望引用update: 更新引用 boolean 对指定索引进行CAS操作lazySet(int i, E newValue) i: 索引newValue: 新引用 void 延迟设置引用import java.util.concurrent.atomic.AtomicReferenceArray;/*** AtomicReferenceArray用于原子更新引用类型数组* 适用于对象引用需要原子更新的场景*/public class AtomicReferenceArrayDemo {static class Person {String name;int age;public Person(String name, int age) {this.name name;this.age age;}Overridepublic String toString() {return name ( age );}}public static void main(String[] args) {Person[] persons {new Person(Alice, 25),new Person(Bob, 30),new Person(Charlie, 35),new Person(David, 40)};AtomicReferenceArrayPerson atomicArray new AtomicReferenceArray(persons);System.out.println(数组长度: atomicArray.length());System.out.println(初始数组: );for (int i 0; i atomicArray.length(); i) {System.out.println(索引 i : atomicArray.get(i));}// 原子更新引用 - 适合对象替换Person newPerson new Person(Eve, 28);Person oldPerson atomicArray.getAndSet(1, newPerson);System.out.println(索引1替换: oldPerson - atomicArray.get(1));// 比较并设置引用boolean success atomicArray.compareAndSet(2, persons[2], new Person(Frank, 45));System.out.println(索引2 CAS结果: success , 新值: atomicArray.get(2));// 延迟设置atomicArray.lazySet(3, new Person(Grace, 50));System.out.println(索引3延迟设置后的值: atomicArray.get(3));// 遍历数组System.out.println(最终数组状态:);for (int i 0; i atomicArray.length(); i) {System.out.println(索引 i : atomicArray.get(i));}}}四、原子更新引用类型4.1 AtomicReference - 原子更新引用类型使用场景单例模式、缓存更新、状态对象替换核心API详解方法 参数 返回值 说明get() - V 获取当前引用set(V newValue) newValue: 新引用 void 设置新引用getAndSet(V newValue) newValue: 新引用 V 原子设置并返回旧引用compareAndSet(V expect, V update) expect: 期望引用update: 更新引用 boolean CAS操作weakCompareAndSet(V expect, V update) expect: 期望引用update: 更新引用 boolean 弱版本CASlazySet(V newValue) newValue: 新引用 void 延迟设置引用updateAndGet(UnaryOperatorV) operator: 更新函数 V 函数式更新getAndUpdate(UnaryOperatorV) operator: 更新函数 V 函数式更新并返回旧值accumulateAndGet(V x, BinaryOperatorV) x: 参数operator: 操作函数 V 累积计算import java.util.concurrent.atomic.AtomicReference;/*** AtomicReference用于原子更新对象引用* 解决先检查后执行的竞态条件*/public class AtomicReferenceDemo {static class User {private String name;private int age;public User(String name, int age) {this.name name;this.age age;}public String getName() { return name; }public int getAge() { return age; }Overridepublic String toString() {return User{name name , age age };}}public static void main(String[] args) {AtomicReferenceUser atomicUser new AtomicReference();User initialUser new User(张三, 25);atomicUser.set(initialUser);System.out.println(初始用户: atomicUser.get());// getAndSet(): 原子更新引用 - 适合缓存更新User newUser new User(李四, 30);User oldUser atomicUser.getAndSet(newUser);System.out.println(替换前的用户: oldUser);System.out.println(当前用户: atomicUser.get());// compareAndSet(): 比较并设置 - 核心操作boolean success atomicUser.compareAndSet(newUser, new User(王五, 35));System.out.println(CAS操作结果: success , 当前用户: atomicUser.get());// weakCompareAndSet(): 弱版本CASboolean weakSuccess atomicUser.weakCompareAndSet(atomicUser.get(), new User(赵六, 40));System.out.println(弱CAS操作结果: weakSuccess , 当前用户: atomicUser.get());// lazySet(): 延迟设置atomicUser.lazySet(new User(孙七, 45));System.out.println(延迟设置后的用户: atomicUser.get());// JDK8新增函数式更新atomicUser.updateAndGet(user - new User(user.getName() _updated, user.getAge() 1));System.out.println(函数式更新后的用户: atomicUser.get());// getAndUpdate(): 函数式更新并返回旧值User previous atomicUser.getAndUpdate(user - new User(周八, 50));System.out.println(更新前的用户: previous , 当前用户: atomicUser.get());// accumulateAndGet(): 累积计算atomicUser.accumulateAndGet(new User(吴九, 55),(old, param) - new User(old.getName() param.getName(),old.getAge() param.getAge()));System.out.println(累积计算后的用户: atomicUser.get());}}典型应用单例模式的双重检查锁定class Singleton {private static final AtomicReferenceSingleton INSTANCE new AtomicReference();public static Singleton getInstance() {for (;;) {Singleton current INSTANCE.get();if (current ! null) return current;current new Singleton();if (INSTANCE.compareAndSet(null, current)) {return current;}}}}4.2 AtomicMarkableReference - 带标记位的原子引用使用场景带状态的缓存、ABA问题简单解决方案核心API详解方法 参数 返回值 说明getReference() - V 获取当前引用isMarked() - boolean 获取当前标记位get(boolean[] markHolder) markHolder: 标记位容器 V 获取引用和标记位set(V newReference, boolean newMark) newReference: 新引用newMark: 新标记 void 设置引用和标记位compareAndSet(V expectedReference, V newReference, boolean expectedMark, boolean newMark) expectedReference: 期望引用newReference: 新引用expectedMark: 期望标记newMark: 新标记 boolean 同时比较引用和标记位attemptMark(V expectedReference, boolean newMark) expectedReference: 期望引用newMark: 新标记 boolean 尝试只更新标记位import java.util.concurrent.atomic.AtomicMarkableReference;/*** AtomicMarkableReference将引用与一个布尔标记位绑定* 适用于需要同时更新引用和状态的场景*/public class AtomicMarkableReferenceDemo {public static void main(String[] args) {String initialRef 初始数据;boolean initialMark false;// 创建带标记位的原子引用AtomicMarkableReferenceString atomicMarkableRef new AtomicMarkableReference(initialRef, initialMark);System.out.println(初始引用: atomicMarkableRef.getReference());System.out.println(初始标记: atomicMarkableRef.isMarked());// get(boolean[]): 同时获取引用和标记位boolean[] markHolder new boolean[1];String currentRef atomicMarkableRef.get(markHolder);System.out.println(当前引用: currentRef , 当前标记: markHolder[0]);// compareAndSet(): 尝试同时更新引用和标记位String newRef 新数据;boolean newMark true;boolean success atomicMarkableRef.compareAndSet(initialRef, newRef, initialMark, newMark);System.out.println(CAS操作结果: success);System.out.println(新引用: atomicMarkableRef.getReference());System.out.println(新标记: atomicMarkableRef.isMarked());// attemptMark(): 只尝试更新标记位boolean markUpdated atomicMarkableRef.attemptMark(newRef, false);System.out.println(标记更新结果: markUpdated);System.out.println(最终标记: atomicMarkableRef.isMarked());// set(): 直接设置引用和标记位atomicMarkableRef.set(最终数据, true);System.out.println(直接设置后的引用: atomicMarkableRef.getReference());System.out.println(直接设置后的标记: atomicMarkableRef.isMarked());}}4.3 AtomicStampedReference - 带版本号的原子引用使用场景解决ABA问题、乐观锁实现核心API详解方法 参数 返回值 说明getReference() - V 获取当前引用getStamp() - int 获取当前版本号get(int[] stampHolder) stampHolder: 版本号容器 V 获取引用和版本号set(V newReference, int newStamp) newReference: 新引用newStamp: 新版本号 void 设置引用和版本号compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp) expectedReference: 期望引用newReference: 新引用expectedStamp: 期望版本号newStamp: 新版本号 boolean 同时比较引用和版本号attemptStamp(V expectedReference, int newStamp) expectedReference: 期望引用newStamp: 新版本号 boolean 尝试只更新版本号import java.util.concurrent.atomic.AtomicStampedReference;/*** AtomicStampedReference通过版本号解决ABA问题* 每次修改都会增加版本号确保不会误判*/public class AtomicStampedReferenceDemo {public static void main(String[] args) {String initialRef 数据A;int initialStamp 0;// 创建带版本号的原子引用AtomicStampedReferenceString atomicStampedRef new AtomicStampedReference(initialRef, initialStamp);System.out.println(初始引用: atomicStampedRef.getReference());System.out.println(初始版本号: atomicStampedRef.getStamp());// get(int[]): 同时获取引用和版本号int[] stampHolder new int[1];String currentRef atomicStampedRef.get(stampHolder);System.out.println(当前引用: currentRef , 当前版本号: stampHolder[0]);// 模拟ABA问题场景String newRefB 数据B;String newRefA 数据A; // 又改回A但版本号不同// 第一次更新A - B版本号 0 - 1boolean firstUpdate atomicStampedRef.compareAndSet(initialRef, newRefB, initialStamp, initialStamp 1);System.out.println(第一次更新(A-B)结果: firstUpdate);System.out.println(当前引用: atomicStampedRef.getReference());System.out.println(当前版本号: atomicStampedRef.getStamp());// 第二次更新B - A版本号 1 - 2boolean secondUpdate atomicStampedRef.compareAndSet(newRefB, newRefA, 1, 2);System.out.println(第二次更新(B-A)结果: secondUpdate);System.out.println(当前引用: atomicStampedRef.getReference());System.out.println(当前版本号: atomicStampedRef.getStamp());// 尝试用旧版本号更新会失败- 这就是解决ABA问题的关键boolean failedUpdate atomicStampedRef.compareAndSet(newRefA, 新数据, 0, 1); // 使用旧的版本号0System.out.println(使用旧版本号更新结果: failedUpdate);System.out.println(引用未被修改: atomicStampedRef.getReference());// attemptStamp(): 只更新版本号boolean stampUpdated atomicStampedRef.attemptStamp(newRefA, 3);System.out.println(版本号更新结果: stampUpdated);System.out.println(新版本号: atomicStampedRef.getStamp());// 正确的方式使用当前版本号stampHolder new int[1];currentRef atomicStampedRef.get(stampHolder);boolean correctUpdate atomicStampedRef.compareAndSet(currentRef, 最终数据, stampHolder[0], stampHolder[0] 1);System.out.println(使用正确版本号更新结果: correctUpdate);System.out.println(最终引用: atomicStampedRef.getReference());System.out.println(最终版本号: atomicStampedRef.getStamp());}}ABA问题详解ABA问题是指线程1读取值A线程2将值改为B然后又改回A线程1进行CAS操作发现当前值仍是A于是操作成功虽然值看起来没变但中间状态的变化可能对业务逻辑产生影响。AtomicStampedReference通过版本号完美解决了这个问题。五、原子更新字段类5.1 AtomicIntegerFieldUpdater - 原子更新整型字段使用场景优化内存使用、大量对象需要原子字段更新核心API详解方法 参数 返回值 说明newUpdater(ClassU tclass, String fieldName) tclass: 目标类fieldName: 字段名 AtomicIntegerFieldUpdaterU 静态方法创建更新器get(U obj) obj: 目标对象 int 获取字段值set(U obj, int newValue) obj: 目标对象newValue: 新值 void 设置字段值getAndSet(U obj, int newValue) obj: 目标对象newValue: 新值 int 原子设置并返回旧值compareAndSet(U obj, int expect, int update) obj: 目标对象expect: 期望值update: 更新值 boolean CAS操作getAndIncrement(U obj) obj: 目标对象 int 原子递增返回旧值getAndDecrement(U obj) obj: 目标对象 int 原子递减返回旧值getAndAdd(U obj, int delta) obj: 目标对象delta: 增量 int 原子加法返回旧值incrementAndGet(U obj) obj: 目标对象 int 原子递增返回新值addAndGet(U obj, int delta) obj: 目标对象delta: 增量 int 原子加法返回新值import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;/*** AtomicIntegerFieldUpdater以原子方式更新对象的volatile int字段* 相比为每个对象创建AtomicInteger可以节省大量内存*/public class AtomicIntegerFieldUpdaterDemo {static class Counter {// 必须用volatile修饰保证可见性public volatile int count;private String name;public Counter(String name, int initialCount) {this.name name;this.count initialCount;}public String getName() { return name; }public int getCount() { return count; }}public static void main(String[] args) {// 创建字段更新器指定要更新的类和字段名AtomicIntegerFieldUpdaterCounter updater AtomicIntegerFieldUpdater.newUpdater(Counter.class, count);Counter counter1 new Counter(计数器1, 0);Counter counter2 new Counter(计数器2, 10);System.out.println(计数器1初始计数: counter1.getCount());System.out.println(计数器2初始计数: counter2.getCount());// get(): 获取字段值System.out.println(通过updater获取计数器1的值: updater.get(counter1));// set(): 设置字段值updater.set(counter1, 5);System.out.println(设置计数器1为5后的值: counter1.getCount());// getAndIncrement(): 原子递增 - 相比synchronized性能更好int oldCount updater.getAndIncrement(counter1);System.out.println(计数器1递增前值: oldCount , 当前值: counter1.getCount());// getAndAdd(): 原子加法oldCount updater.getAndAdd(counter1, 10);System.out.println(计数器1加10前值: oldCount , 当前值: counter1.getCount());// incrementAndGet(): 原子递增并返回新值int newCount updater.incrementAndGet(counter1);System.out.println(计数器1递增后的值: newCount);// addAndGet(): 原子加法并返回新值newCount updater.addAndGet(counter1, 20);System.out.println(计数器1加20后的值: newCount);// compareAndSet(): 比较并设置boolean updated updater.compareAndSet(counter1, 36, 50);System.out.println(计数器1 CAS操作结果: updated , 当前值: counter1.getCount());// 可以同时更新多个对象的相同字段updater.incrementAndGet(counter2);System.out.println(计数器2递增后的值: counter2.getCount());}}内存优化效果AtomicInteger对象16-24字节 overheadvolatile int AtomicIntegerFieldUpdater4字节 静态updater当有大量对象时内存节省效果显著5.2 AtomicLongFieldUpdater - 原子更新长整型字段使用场景大数值字段的原子更新、内存敏感场景核心API详解方法 参数 返回值 说明newUpdater(ClassU tclass, String fieldName) tclass: 目标类fieldName: 字段名 AtomicLongFieldUpdaterU 静态方法创建更新器get(U obj) obj: 目标对象 long 获取字段值set(U obj, long newValue) obj: 目标对象newValue: 新值 void 设置字段值getAndSet(U obj, long newValue) obj: 目标对象newValue: 新值 long 原子设置并返回旧值compareAndSet(U obj, long expect, long update) obj: 目标对象expect: 期望值update: 更新值 boolean CAS操作getAndAdd(U obj, long delta) obj: 目标对象delta: 增量 long 原子加法返回旧值addAndGet(U obj, long delta) obj: 目标对象delta: 增量 long 原子加法返回新值import java.util.concurrent.atomic.AtomicLongFieldUpdater;/*** AtomicLongFieldUpdater用于原子更新long字段* 适用于需要大数值范围且内存敏感的场景*/public class AtomicLongFieldUpdaterDemo {static class Account {// 必须用volatile修饰public volatile long balance;private final String owner;public Account(String owner, long initialBalance) {this.owner owner;this.balance initialBalance;}public String getOwner() { return owner; }public long getBalance() { return balance; }}public static void main(String[] args) {AtomicLongFieldUpdaterAccount balanceUpdater AtomicLongFieldUpdater.newUpdater(Account.class, balance);Account account1 new Account(张三, 1000L);Account account2 new Account(李四, 2000L);System.out.println(张三账户初始余额: account1.getBalance());System.out.println(李四账户初始余额: account2.getBalance());// 基础操作System.out.println(通过updater获取张三余额: balanceUpdater.get(account1));balanceUpdater.set(account1, 1500L);System.out.println(设置张三余额为1500后的值: account1.getBalance());// 原子存款 - 无锁线程安全balanceUpdater.addAndGet(account1, 500L);System.out.println(张三存款500后余额: account1.getBalance());// 原子取款long oldBalance balanceUpdater.getAndAdd(account1, -200L);System.out.println(张三取款200前余额: oldBalance , 取款后余额: account1.getBalance());// 比较并设置 - 实现转账等业务boolean transferSuccess balanceUpdater.compareAndSet(account1, 1800L, 2000L);System.out.println(张三转账操作结果: transferSuccess , 当前余额: account1.getBalance());// 同时操作多个账户balanceUpdater.getAndAdd(account2, 1000L);System.out.println(李四存款1000后余额: account2.getBalance());}}5.3 AtomicReferenceFieldUpdater - 原子更新引用字段使用场景链表节点更新、树结构调整、对象关系维护核心API详解方法 参数 返回值 说明newUpdater(ClassU tclass, ClassW vclass, String fieldName) tclass: 目标类vclass: 字段类型fieldName: 字段名 AtomicReferenceFieldUpdaterU,W 静态方法创建更新器get(U obj) obj: 目标对象 V 获取字段引用set(U obj, V newValue) obj: 目标对象newValue: 新引用 void 设置字段引用getAndSet(U obj, V newValue) obj: 目标对象newValue: 新引用 V 原子设置并返回旧引用compareAndSet(U obj, V expect, V update) obj: 目标对象expect: 期望引用update: 更新引用 boolean CAS操作lazySet(U obj, V newValue) obj: 目标对象newValue: 新引用 void 延迟设置引用import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;/*** AtomicReferenceFieldUpdater用于原子更新引用字段* 常用于实现无锁数据结构*/public class AtomicReferenceFieldUpdaterDemo {static class NodeT {// 必须用volatile修饰public volatile NodeT next;private final T value;public Node(T value) {this.value value;}public T getValue() { return value; }public NodeT getNext() { return next; }Overridepublic String toString() {return Node{value value , next (next ! null ? next.value : null) };}}public static void main(String[] args) {// 创建引用字段更新器AtomicReferenceFieldUpdaterNode, Node nextUpdater AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, next);NodeString first new Node(第一个节点);NodeString second new Node(第二个节点);NodeString third new Node(第三个节点);System.out.println(初始第一个节点的next: first.getNext());// get(): 获取字段引用System.out.println(通过updater获取第一个节点的next: nextUpdater.get(first));// set(): 设置字段引用nextUpdater.set(first, second);System.out.println(设置第一个节点的next为第二个节点: first);// compareAndSet(): 原子设置next字段 - 实现无锁链表boolean setSuccess nextUpdater.compareAndSet(first, second, third);System.out.println(CAS操作结果: setSuccess);System.out.println(第一个节点: first);// getAndSet(): 获取并设置引用NodeString oldNext nextUpdater.getAndSet(second, third);System.out.println(第二个节点原来的next: oldNext);System.out.println(第二个节点: second);// lazySet(): 延迟设置nextUpdater.lazySet(third, first); // 形成环状仅作演示System.out.println(第三个节点延迟设置后的next: third.getNext());// 构建链表并展示System.out.println(最终链表结构:);NodeString current first;int count 0;while (current ! null count 5) { // 防止无限循环System.out.println(current);current current.getNext();count;}}}六、综合实战构建线程安全计数器下面我们通过一个综合示例展示如何在实际项目中使用原子操作类import java.util.concurrent.atomic.*;import java.util.concurrent.*;/*** 线程安全计数器综合示例* 展示了多种原子类的实际应用*/public class ThreadSafeCounter {// 基本计数器 - 使用AtomicIntegerprivate final AtomicInteger count new AtomicInteger(0);// 大数值统计 - 使用AtomicLongprivate final AtomicLong total new AtomicLong(0L);// 状态控制 - 使用AtomicReferenceprivate final AtomicReferenceString status new AtomicReference(RUNNING);// 统计数组 - 使用AtomicIntegerArray进行分桶统计private final AtomicIntegerArray bucketStats new AtomicIntegerArray(10);// 配置信息 - 使用AtomicReference支持动态更新private final AtomicReferenceConfig config new AtomicReference(new Config(100, 60));// 标记位控制 - 使用AtomicBooleanprivate final AtomicBoolean enabled new AtomicBoolean(true);static class Config {final int maxConnections;final int timeoutSeconds;public Config(int maxConnections, int timeoutSeconds) {this.maxConnections maxConnections;this.timeoutSeconds timeoutSeconds;}Overridepublic String toString() {return Config{maxConnections maxConnections , timeoutSeconds timeoutSeconds };}}// 核心API方法public void increment() {if (!enabled.get()) {System.out.println(计数器已禁用忽略操作);return;}count.incrementAndGet();total.addAndGet(1L);// 分桶统计根据count值决定放入哪个桶int bucket count.get() % 10;bucketStats.getAndIncrement(bucket);}public void add(int value) {if (!enabled.get()) {System.out.println(计数器已禁用忽略操作);return;}count.addAndGet(value);total.addAndGet(value);}public boolean setStatus(String expected, String newStatus) {return status.compareAndSet(expected, newStatus);}public void updateConfig(Config newConfig) {Config oldConfig;do {oldConfig config.get();System.out.println(尝试更新配置: oldConfig - newConfig);} while (!config.compareAndSet(oldConfig, newConfig));System.out.println(配置更新成功);}public boolean enable() {return enabled.compareAndSet(false, true);}public boolean disable() {return enabled.compareAndSet(true, false);}// 获取统计信息public void printStats() {System.out.println(\n 统计信息 );System.out.println(当前计数: count.get());System.out.println(总数: total.get());System.out.println(状态: status.get());System.out.println(启用状态: enabled.get());System.out.println(桶统计: bucketStats.toString());Config currentConfig config.get();System.out.println(配置: currentConfig);// 验证数据一致性long sum 0;for (int i 0; i bucketStats.length(); i) {sum bucketStats.get(i);}System.out.println(桶统计总和: sum , 计数: count.get() , 一致性: (sum count.get()));}public static void main(String[] args) throws InterruptedException {ThreadSafeCounter counter new ThreadSafeCounter();// 创建多个线程同时操作计数器int threadCount 10;int operationsPerThread 1000;ExecutorService executor Executors.newFixedThreadPool(threadCount);CountDownLatch latch new CountDownLatch(threadCount);System.out.println(开始并发测试...);for (int i 0; i threadCount; i) {final int threadId i;executor.execute(() - {try {for (int j 0; j operationsPerThread; j) {counter.increment();// 每隔一定操作数更新配置if (j % 200 0) {counter.updateConfig(new Config(100 j, 60));}// 模拟随机禁用/启用if (j 500 threadId 0) {System.out.println(线程 threadId 尝试禁用计数器);counter.disable();Thread.sleep(10); // 短暂休眠System.out.println(线程 threadId 尝试启用计数器);counter.enable();}