mindmap
JUC
原子类
AtomicInteger
AtomicReference
并发队列
LinkedBlockingQueue
ArrayBlockingQueue
ConcurrentLinkedDeque
ConcurrentLinkedQueue
同步工具
CountDownLatch
Semaphore
CyclicBarrier
Exchanger
并发集合
ConcurrentHashMap
CopyOnWriteArrayList
CopyOnWriteArraySet
ConcurrentSkipListMap
并发锁
ReentrantLock
ReentrantReadWriteLock
线程池
Executor
Fork/Join
原子类
1.Java原子类的实现原理
Java原子类主要依赖CAS(Compare and Swap)操作和volatile变量,通过无锁编程实现线程安全。
核心机制(CAS)
- 定义:CAS是一种硬件支持的原子操作,通过比较内存与预期值,若匹配则更新为新值。
- 操作语义:
boolean CAS(address, expectedValue, newValue) {
if (*address == expectedValue) {
*address = newValue;
return true;
}
return false;
}
- 硬件支持:通过CPU指令(如x86的Lock CMPXHG)实现原子类。
2.原子类的实现步骤
- 使用volatile保证可见性(如AtomicInteger的value)会用volatile修饰:
public class AtomicInteger{
//作用:确保每次读取到最新值,避免脏读
private volatile int value;
}
- 通过Unsafe类调用底层CAS
- Unsafe类:提供直接操作内存和线程的底层compareAndSwapInt方法
- 原子类封装CAS
- 内存偏移量valueOffset:通过反射获取字段在对象内存中的位置
- CAS调用compareAndSet:直接操作内存地址实现原子更新
public class AtomicInteger {
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset; // value 字段的内存偏移量
static {
try {
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
}
- 循环CAS解决竞争
- 自旋重试:若CAS失败,则循环尝试直到成功
public final int incrementAndGet() {
int current;
do {
current = get(); // 读取当前值(volatile 保证最新值)
} while (!compareAndSet(current, current + 1)); // CAS 更新
return current + 1;
}
3.解决ABA问题
- ABA问题:线程1读取值为A,之后值被其他线程修改为B又改回A,对于线程1而言仍然会成功,这里可能会导致逻辑错误。
- 解决方案:AtomicStampedReference通过版本号(Stamp)标记值的变更
AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(100, 0);
int stamp = ref.getStamp();
ref.compareAndSet(100, 101, stamp, stamp + 1); // 同时检查值和版本号
LongAdder 对比 AtomicLong
| 特性 | AtomicLong | LonAdder |
|---|---|---|
| 实现方式 | 单一volatile变量+CAS | 分散Cell数组+CAS |
| 高并发性能 | 差(CAS竞争激烈时自旋次数过多) | 优(分散热点,减少竞争) |
| 使用场景 | 低并发计数 | 高并发统计(如QPS计数器) |
- LongAdder原理:
- 将值分散到多个cell中,线程竞争时优先更新各自Cell。
- 最终结果通过合并所有Cell的值得到。
5.内存屏障与有序性
- volatile写:插入StoreStore + StoreLoad屏障,确保写操作对其他线程可见。
- volatile读:插入LoadLoad + LoadStore屏障,禁止重排序。
总结
Java原子类(如
AtomicInteger)通过 CAS 操作 和 volatile 变量 实现线程安全:
- volatile 保证值的可见性;
- Unsafe 类 调用底层 CAS 指令确保原子性;
- 循环 CAS 解决多线程竞争;
- 高并发场景下,
LongAdder通过分散热点优化性能;AtomicStampedReference解决 ABA 问题。
这种无锁设计在高并发下比synchronized更高效,但需注意自旋开销和 ABA 风险。”