Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程创建与任务模型
    • 线程安全
    • synchronized关键字
    • volatile关键字
    • Java内存模型(JMM)
      • 1. 为什么需要 JMM
      • 2. 主内存与工作内存
      • 3. 三大问题
      • 4. happens-before
      • 5. 常见 happens-before 规则
      • 6. synchronized 的 JMM 语义
      • 7. volatile 的 JMM 语义
      • 8. final 字段语义
      • 9. 重排序
      • 10. 安全发布
      • Tips 快问快答
    • 线程间通信
    • 线程池
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
    • ThreadLocal
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
    • 虚拟线程
    • 死锁活锁与线程问题排查
    • 并发编程最佳实践
  • Java IO

  • JVM

  • Java
  • Java并发
Wray
2026-06-24
目录

Java内存模型(JMM)

Java 内存模型,简称 JMM,定义了多线程环境下变量如何读写、线程之间如何看到彼此的修改,以及哪些操作之间存在 happens-before 关系。

JMM 是理解 volatile、synchronized、final、线程启动和线程结束可见性的基础。

# 1. 为什么需要 JMM

现代程序会经过多层优化:

  • 编译器优化。
  • JIT 优化。
  • CPU 缓存。
  • CPU 指令重排序。
  • 写缓冲区。

如果没有统一规范,不同平台上同一段 Java 并发代码可能表现不同。

JMM 的目标是屏蔽底层差异,为 Java 程序提供统一的并发语义。

# 2. 主内存与工作内存

概念模型:

主内存
┌────────────────────┐
│ shared variables   │
└─────────┬──────────┘
          │
          ▼
线程 A 工作内存       线程 B 工作内存
┌──────────────┐     ┌──────────────┐
│ shared 副本   │     │ shared 副本   │
└──────────────┘     └──────────────┘

线程不能直接操作主内存中的变量概念值,而是通过自己的工作内存副本进行读写,再与主内存同步。

这只是规范模型,不等同于真实硬件结构。

# 3. 三大问题

问题 示例 解决
原子性 count++ 更新丢失 锁、原子类
可见性 一个线程改了标记,另一个线程看不到 volatile、锁
有序性 指令重排序导致观察到异常顺序 volatile、锁、happens-before

JMM 主要解决可见性和有序性规则,原子性还需要锁或原子操作配合。

# 4. happens-before

happens-before 表示前一个操作的结果对后一个操作可见,并且前一个操作在内存语义上排在后一个操作之前。

A happens-before B
   │
   ▼
B 能看到 A 的结果

它不一定等同于物理时间先后,而是 JMM 定义的可见性顺序。

# 5. 常见 happens-before 规则

规则 说明
程序次序规则 同一线程内,前面的操作 happens-before 后面的操作
监视器锁规则 unlock happens-before 后续对同一锁的 lock
volatile 规则 volatile 写 happens-before 后续同变量 volatile 读
线程启动规则 Thread.start() happens-before 新线程内动作
线程终止规则 线程内动作 happens-before 其他线程检测到它结束
中断规则 interrupt() happens-before 被中断线程检测到中断
传递性 A hb B,B hb C,则 A hb C

示例:

int value = 0;
volatile boolean ready = false;

// 线程 A
value = 42;
ready = true;

// 线程 B
if (ready) {
    System.out.println(value); // 能看到 42
}

# 6. synchronized 的 JMM 语义

线程 A synchronized(lock) 写共享变量
  │ unlock
  ▼
线程 B synchronized(lock) 读共享变量

同一把锁的释放和获取建立 happens-before。

因此 synchronized 不只是互斥,还保证进入锁的线程能看到之前持锁线程释放锁前的写入。

# 7. volatile 的 JMM 语义

普通写
普通写
volatile 写
   │
   ▼
volatile 读
普通读
普通读

读到 volatile 写的线程,可以看到写 volatile 前的普通写。

这常用于状态发布。

# 8. final 字段语义

final 字段有特殊初始化安全保证。

public class Config {
    private final int timeout;

    public Config(int timeout) {
        this.timeout = timeout;
    }
}

只要构造期间 this 没有逃逸,其他线程看到构造完成的对象时,应能看到正确的 final 字段值。

不要在构造器中把 this 暴露给其他线程:

public Config() {
    Global.registry(this); // this 逃逸,不推荐
}

# 9. 重排序

在不改变单线程语义的前提下,编译器和 CPU 可能调整指令顺序。

单线程看起来没问题,多线程可能暴露问题。

data = 1;
ready = true;

如果没有同步,另一个线程可能先看到 ready=true,却还看不到 data=1。

JMM 通过 volatile、锁等机制限制这种重排序的可见影响。

# 10. 安全发布

安全发布方式:

  • 使用静态初始化。
  • 使用 volatile 引用。
  • 使用 final 字段正确构造。
  • 使用锁保护。
  • 放入线程安全容器。

示例:

private volatile Config config;

public void refresh() {
    config = new Config(1000);
}

# Tips 快问快答

Q:JMM 是真实内存结构吗? A:不是,它是 Java 规范中的抽象内存模型。

Q:happens-before 表示时间先后吗? A:不完全是,它表示内存可见性和顺序关系。

Q:synchronized 只保证互斥吗? A:不只,它还保证同一锁释放和获取之间的可见性。

Q:volatile 写和读有什么关系? A:volatile 写 happens-before 后续对同一变量的 volatile 读。

Q:final 字段一定安全吗? A:正确构造且 this 不逃逸时,final 字段有初始化安全保证。

Q:为什么单线程没问题,多线程可能出错? A:因为多线程涉及可见性、重排序和竞争时序。

Q:安全发布是什么意思? A:让其他线程看到对象引用时,也能看到对象正确初始化后的状态。

Q:JMM 主要解决什么? A:定义多线程下变量读写、可见性、有序性和 happens-before 规则。

上次更新: 2026/06/24, 17:22:59
volatile关键字
线程间通信

← volatile关键字 线程间通信→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式