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

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

相关推荐
顾城猿6 小时前
STOMP 协议
java
郑州光合科技余经理6 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
知识分享小能手6 小时前
C++ 学习教程,从入门到精通,C++ 入门知识 — 完整知识点(1)
开发语言·c++·学习
+VX:Fegn08957 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
IT_陈寒7 小时前
Vue的响应式让我熬到凌晨三点,原来漏了这个小细节
前端·人工智能·后端
需要8267 小时前
MySQL 索引 B+ 树与“查询为什么变慢了
java·spring boot·spring·spring cloud·tomcat
一 乐7 小时前
二手交易平台|基于springboot + vue二手交易平台(源码+数据库+文档)
java·数据库·vue.js·spring boot·小程序
万年咸鱼7 小时前
编译Java源程序
java
Wang's Blog7 小时前
Java 项目实战: 外卖平台-删除分类的关联校验与自定义业务异常
java·服务器·项目开发
阿里嘎多学长7 小时前
2026-09-20 GitHub 热点项目精选
开发语言·程序员·github·代码托管