原子性指操作不可分割、不可中断,要么全执行要么不执行;java中int等基本类型单次读写天然原子,而i++等复合操作因含读-改-写三步而非原子,需atomicinteger或synchronized保障。

原子性操作在多线程中,核心是“不可分割”——一个操作要么完整执行,要么根本不发生,中间状态对其他线程不可见。
原子性不是看代码行数,而是看底层是否可中断
比如 a = 1(a 是 int 类型)是原子操作,CPU 一条指令就能完成赋值;但 a++ 看似简单,实际包含“读取 a → 加 1 → 写回 a”三步,多线程下可能被交叉执行,导致结果丢失。
- 多个线程同时执行 1000 次 a++,最终 a 可能远小于 2000,这就是非原子操作引发的竞态条件
- long 和 double 在 32 位 JVM 上的读写不保证原子性(分高低 32 位两次操作),需用 volatile 或 AtomicLong 保障
Java 如何提供原子性保障
JMM 本身只保证基本类型(除 long/double 外)的读写原子性,更复杂的原子行为需要显式手段:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- synchronized:进入同步块前加锁,退出时释放锁,整个块内操作对其他线程互斥,天然具备原子性
- Lock 接口(如 ReentrantLock):比 synchronized 更灵活,同样通过排他锁实现临界区原子性
- AtomicXXX 类(如 AtomicInteger):基于 CAS(Compare-And-Swap)硬件指令,无锁但保证单个变量更新的原子性
哪些操作天然具备原子性?哪些容易踩坑?
基础读写(如 int、boolean 的赋值)是原子的,但复合逻辑不是。关键要区分“操作语义”和“JVM 行为”:
- ✅
flag = true、count = 5—— 原子 - ❌
count++、list.add(x)、map.put(k, v)—— 非原子,需额外同步 - ⚠️
volatile long timestamp能保证可见性和禁止重排序,但不能单独保证 long 写入的原子性(仍需 AtomicLong 或 synchronized)
CAS 是怎么做到无锁原子性的?
CAS 是 CPU 提供的原生指令,一次完成“比较 + 交换”,操作系统和 JVM 无法中断它:
- AtomicInteger 的
incrementAndGet()底层就是循环调用 CAS:检查当前值是否等于预期值,是则更新,否则重试 - 它适合低竞争场景;高竞争时反复失败重试会增加开销,此时 synchronized 反而更稳定
- CAS 只能保证单个变量的原子更新,多个变量关联修改(如转账:A 减、B 加)仍需锁来保证整体原子性
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










