Java并发原生工具:原子类 (Atomic Classes)

核心速览

java.util.concurrent.atomic包提供无锁、高性能的线程安全工具,基于 CAS (Compare-And-Swap)​ 与 VarHandle(JDK 9+)实现,避免 synchronized阻塞开销,适用于单变量原子更新。

核心原理:通过 CPU CAS 指令(比较并交换)保证原子性;JDK 9 起推荐 VarHandle(替代 Unsafe),JDK 21 原子类全面基于 VarHandle。

关键分类:

  • 基本类型:AtomicInteger(32位)、AtomicLong(64位)、AtomicBoolean(仅布尔值,无算术操作);
  • 引用类型:AtomicReference(对象引用)、AtomicStampedReference(带版本号解决ABA)、AtomicMarkableReference(带标记简化ABA);
  • 数组类型:AtomicIntegerArray等(原子更新数组单个元素);
  • 高并发优化:LongAdder/DoubleAdder(分段累加,高并发计数性能远超 AtomicLong)。

原子类是 java.util.concurrent.atomic 包下的一组高性能、无锁(lock-free)线程安全工具,用于在多线程环境下安全地更新单个变量,无需使用 synchronizedReentrantLock。它们是实现无锁并发编程的核心组件。

核心原理:CAS 与 VarHandle

  • count++ 的非原子性

    该操作在字节码层面包含三步:读取 → 加1 → 写回。在多线程下,这些步骤可能交错执行,导致更新丢失。

  • 传统方案:加锁

    使用 synchronized 可以保证安全,但会带来上下文切换、竞争和阻塞的开销。

  • 原子类方案:CAS

    原子类通过 CPU 的 CAS (Compare-And-Swap) 指令实现原子操作,避免了锁的开销,在低到中等竞争场景下性能显著优于锁。其早期实现依赖 sun.misc.Unsafe,但从 JDK 9 起,官方推荐使用 java.lang.invoke.VarHandle 作为底层标准 API。

  • VarHandle 的核心方法
    VarHandle 提供了更安全、可移植的底层访问能力,支持以下操作:

    • compareAndSet(expected, value)
    • getAndSet(value)
    • getAndAdd(delta)
    • getAcquire() / setRelease()
  • JDK 21 及以后

    所有原子类(如 AtomicInteger)内部已全面基于 VarHandle 实现。


原子类分类与用法

1、基本类型原子类

用于原子化地更新 booleanintlong 等基本类型。

说明 常用方法
AtomicBoolean 原子布尔值 get(), set(newValue), compareAndSet(expect, update), getAndAdd(delta)
AtomicInteger 原子整型 (32位) 同上
AtomicLong 原子长整型 (64位) 同上

2、引用类型原子类

用于原子化地更新对象引用,解决对象引用的并发问题。

说明 示例
AtomicReference<T> 原子引用 AtomicReference<String> ref = new AtomicReference<>("hello"); ref.compareAndSet("hello", "world");
AtomicMarkableReference<T> 带 boolean 标记的引用 用于解决 ABA 问题的简化方案。
AtomicStampedReference<T> 带 int "戳"的引用 通过版本号解决更通用的 ABA 问题。

3、数组类型原子类

保证对数组中单个元素的操作是原子的,而非整个数组。

说明 注意
AtomicIntegerArray 原子整型数组 操作指定索引的元素。
AtomicLongArray 原子长整型数组 同上。
AtomicReferenceArray<T> 原子引用数组 同上。

4、高并发优化类 (Java 8+)

LongAdderDoubleAdder 专为高并发写场景(如计数器)设计。在激烈竞争下,AtomicLong 因 CAS 失败重试频繁而性能下降,而 LongAdder 通过分段累加(cell 机制)大幅降低了竞争,性能更优。


常见误区

  1. 误区 1:atomic.get() + 1 是原子操作

    java

    // 错误!非原子操作

    int newVal = atomic.get() + 1;

    atomic.set(newVal);

    必须使用 incrementAndGet()getAndIncrement() 等原子方法。

  2. 误区 2:compareAndSet 一定会成功

    在高竞争或 ABA 问题下可能失败,通常需要配合循环重试逻辑。LongAdder 在高并发计数场景下是更优选择。


最佳实践

  1. 优先使用 LongAdder / DoubleAdder:作为计数器,尤其在写并发高的场景。
  2. 避免复合操作 :如 if (atomic.get() < 100) atomic.increment();,这需要外部同步来保证原子性。
  3. 勿用于复杂状态机 :对于复杂的状态流转,应使用 synchronizedjava.util.concurrent 中的高级工具(如 Phaser, StampedLock)。
  4. 使用标准 API :在 JDK 9+ 中,应使用 VarHandle 而非 sun.misc.Unsafe

一键三连,让我的信心像气球一样膨胀!

相关推荐
草履虫建模17 小时前
力扣算法 1768. 交替合并字符串
java·开发语言·算法·leetcode·职场和发展·idea·基础
naruto_lnq19 小时前
分布式系统安全通信
开发语言·c++·算法
qq_2975746719 小时前
【实战教程】SpringBoot 实现多文件批量下载并打包为 ZIP 压缩包
java·spring boot·后端
老毛肚19 小时前
MyBatis插件原理及Spring集成
java·spring·mybatis
学嵌入式的小杨同学19 小时前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
lang2015092819 小时前
JSR-340 :高性能Web开发新标准
java·前端·servlet
Re.不晚20 小时前
Java入门17——异常
java·开发语言
缘空如是20 小时前
基础工具包之JSON 工厂类
java·json·json切换
精彩极了吧20 小时前
C语言基本语法-自定义类型:结构体&联合体&枚举
c语言·开发语言·枚举·结构体·内存对齐·位段·联合
追逐梦想的张小年20 小时前
JUC编程04
java·idea