java中基本类型(boolean、byte、short、char、int、float)和引用类型赋值是原子操作;volatile修饰的long/double赋值也是原子的,但i++等读-改-写操作非原子,且原子性不等于线程安全。

Java 中基本数据类型的简单赋值操作(如 int x = 5;、boolean flag = true;)在绝大多数现代 JVM(JDK 8+、64 位主流平台)上是原子的,但“不能保证绝对的原子性”这个说法成立——关键在于它**依赖 JVM 实现、硬件平台和数据类型本身,并非语言规范的刚性承诺**。
long 和 double 在 32 位 JVM 上可能被“撕裂”
Java 规范只要求对 不大于 32 位的数据读写必须原子。而 long 和 double 是 64 位类型,在部分旧环境(如某些 32 位 JVM 或嵌入式平台)中,它们的赋值可能被拆成两次 32 位操作:
- 线程 A 正在执行
long val = 0x1111222233334444L; - 只写入了高 32 位(
0x11112222),还没来得及写低 32 位,就被中断 - 此时线程 B 读取
val,可能拿到0x11112222AAAAAAAA(高半截新、低半截旧)——这就是“撕裂读”
这种风险真实存在,且不依赖多线程竞争逻辑,仅由底层执行模型导致。
JVM 规范本身未强制要求 64 位操作原子
《Java 虚拟机规范》明确说明:仅 boolean、byte、short、char、int、float 的读写,以及所有引用类型赋值,被保证为原子操作;long/double 不在此列。这意味着:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 是否原子,由具体 JVM 实现决定
- 不同厂商(HotSpot、OpenJ9)、不同版本、不同 CPU 架构(x86 vs ARM)行为可能不同
- 你不能在跨平台、长期维护的代码中,假设
long count = 1000;在任何环境下都绝对安全
“简单赋值”不等于“线程安全”
即使 int x = 1; 这条语句本身原子,多个线程并发执行它仍可能出问题:
- 线程 A 执行
x = 1;,线程 B 同时执行x = 2; - 虽然每次写入动作原子,但最终结果可能是 1 或 2,无法预测,且没有机制保证其他线程能及时看到最新值
- 这已超出原子性范畴,进入可见性与竞态控制领域——而原子性只是线程安全的必要非充分条件
volatile 是补救,不是默认保障
对 long 和 double 加上 volatile 修饰,可强制 JVM 将其读写作为单次原子操作处理(通过插入内存屏障、禁止重排序、确保主存直通)。但这恰恰反向证明:没有 volatile 时,它们的原子性并不默认成立。
换句话说,volatile 不是“增强原子性”,而是“修复本不保证的原子性边界”,尤其针对 64 位变量。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










