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

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

相关推荐
大鸡腿同学3 小时前
【成长类】《只有偏执狂才能生存》读书笔记:程序员的偏执型成长地图
后端
0xDevNull3 小时前
MySQL数据冷热分离详解
后端·mysql
一定要AK3 小时前
Spring 入门核心笔记
java·笔记·spring
A__tao3 小时前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
AI袋鼠帝3 小时前
OpenClaw(龙虾)最强开源对手!Github 40K Star了,又一个爆火的Agent..
后端
KevinCyao4 小时前
java视频短信接口怎么调用?SpringBoot集成视频短信及回调处理Demo
java·spring boot·音视频
lly2024064 小时前
C 标准库 - `<stdio.h>`
开发语言
沫璃染墨4 小时前
C++ string 从入门到精通:构造、迭代器、容量接口全解析
c语言·开发语言·c++
jwn9994 小时前
Laravel6.x核心特性全解析
开发语言·php·laravel
迷藏4944 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源