原子类
java.util.concurrent.atomic 包提供了原子操作类,基于 CAS(Compare-And-Swap)实现无锁线程安全。
1. 什么是 CAS
CAS 是一种无锁算法,包含三个操作数:
- V:内存值(要更新的变量)
- E:预期值(期望的旧值)
- N:新值
原理:当且仅当 V == E 时,才将 V 更新为 N,否则不做任何操作。
if (V == E) {
V = N
return true
} else {
return false
}2. 基本类型原子类
2.1 AtomicInteger
java
import java.util.concurrent.atomic.*;
AtomicInteger atomicInt = new AtomicInteger(0);
// 自增
atomicInt.incrementAndGet(); // ++i,返回新值
atomicInt.getAndIncrement(); // i++,返回旧值
// 自减
atomicInt.decrementAndGet(); // --i
atomicInt.getAndDecrement(); // i--
// 加法
atomicInt.addAndGet(10); // i += 10,返回新值
atomicInt.getAndAdd(10); // 返回旧值
// CAS 操作
boolean success = atomicInt.compareAndSet(10, 20);
// 获取并更新
atomicInt.getAndUpdate(x -> x * 2);
// 累加器
atomicInt.accumulateAndGet(5, Integer::sum);2.2 其他基本类型
java
AtomicLong atomicLong = new AtomicLong(0);
AtomicBoolean atomicBoolean = new AtomicBoolean(false);2.3 使用示例
java
// 线程安全的计数器
public class Counter {
private AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}3. 引用类型原子类
3.1 AtomicReference
java
import java.util.concurrent.atomic.*;
AtomicReference<User> atomicRef = new AtomicReference<>(new User("Tom"));
// CAS 更新
User expected = atomicRef.get();
User newUser = new User("Jerry");
boolean success = atomicRef.compareAndSet(expected, newUser);
// getAndUpdate
User old = atomicRef.getAndUpdate(user -> new User(user.getName() + "_updated"));3.2 ABA 问题
CAS 存在 ABA 问题:值从 A 变成 B,又变回 A,CAS 会认为没有变化。
线程1:读取值 A
线程2:A → B → A
线程1:CAS(A, C) 成功,但实际上值已经被修改过3.3 AtomicStampedReference(解决 ABA)
通过版本号(stamp)解决 ABA 问题。
java
AtomicStampedReference<Integer> stampedRef = new AtomicStampedReference<>(1, 0);
// 获取值和版本号
int[] stampHolder = new int[1];
Integer value = stampedRef.get(stampHolder);
int stamp = stampHolder[0];
// CAS 时同时验证值和版本号
boolean success = stampedRef.compareAndSet(
value, // 期望值
value + 1, // 新值
stamp, // 期望版本号
stamp + 1 // 新版本号
);3.4 AtomicMarkableReference
使用布尔标记代替版本号。
java
AtomicMarkableReference<Integer> markableRef = new AtomicMarkableReference<>(1, false);
boolean[] markHolder = new boolean[1];
Integer value = markableRef.get(markHolder);
boolean marked = markHolder[0];
markableRef.compareAndSet(value, value + 1, marked, !marked);4. 数组原子类
java
import java.util.concurrent.atomic.*;
// 整型数组
AtomicIntegerArray atomicArray = new AtomicIntegerArray(10);
atomicArray.getAndIncrement(0); // 索引0的元素自增
atomicArray.addAndGet(1, 10); // 索引1的元素加10
// 长整型数组
AtomicLongArray atomicLongArray = new AtomicLongArray(new long[]{1, 2, 3});
// 引用数组
AtomicReferenceArray<String> atomicRefArray = new AtomicReferenceArray<>(10);
atomicRefArray.set(0, "hello");5. 字段更新器
可以原子更新对象的某个字段,无需继承原子类。
5.1 AtomicIntegerFieldUpdater
java
import java.util.concurrent.atomic.*;
public class User {
private volatile int age; // 必须是 volatile
private static final AtomicIntegerFieldUpdater<User> AGE_UPDATER =
AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
public void incrementAge() {
AGE_UPDATER.incrementAndGet(this);
}
public int getAge() {
return age;
}
}5.2 限制条件
- 字段必须是
volatile - 字段不能是
private(对于其他类) - 字段不能是
static
6. LongAdder 和 LongAccumulator
6.1 LongAdder
高性能计数器,适合高并发场景。
java
import java.util.concurrent.atomic.*;
LongAdder adder = new LongAdder();
// 累加
adder.increment();
adder.add(10);
// 获取值
long sum = adder.sum();6.2 vs AtomicLong
| 特性 | AtomicLong | LongAdder |
|---|---|---|
| 实现 | 单个变量 CAS | 分散热点 |
| 高并发性能 | 较低 | 较高 |
| 获取精确值 | ✅ | ⚠️ 仅适合最终汇总 |
| 适用场景 | 低并发 | 高并发统计 |
原理:LongAdder 在内部维护多个变量,减少竞争。
AtomicLong:
所有线程竞争同一个变量 → 高冲突
LongAdder:
┌─────┐ ┌─────┐ ┌─────┐
│Cell1│ │Cell2│ │Cell3│ → 分散到多个 Cell
└─────┘ └─────┘ └─────┘
│ │ │
└────────┼────────┘
│
sum() 汇总6.3 LongAccumulator
更通用的累加器,支持自定义累加函数。
java
// 求最大值
LongAccumulator max = new LongAccumulator(Long::max, Long.MIN_VALUE);
max.accumulate(10);
max.accumulate(20);
max.accumulate(5);
System.out.println(max.get()); // 20
// 求乘积
LongAccumulator product = new LongAccumulator((x, y) -> x * y, 1);
product.accumulate(2);
product.accumulate(3);
product.accumulate(4);
System.out.println(product.get()); // 247. 原子类选择指南
| 场景 | 推荐类 |
|---|---|
| 简单计数器 | AtomicInteger / AtomicLong |
| 高并发计数器 | LongAdder |
| 原子更新对象 | AtomicReference |
| 解决 ABA 问题 | AtomicStampedReference |
| 原子更新数组元素 | AtomicIntegerArray |
| 原子更新对象字段 | AtomicIntegerFieldUpdater |