一、为什么需要内存模型(JMM)?
在多核CPU时代,并发编程是提升程序性能的核心手段,但是并发带来了三大经典问题:
可见性问题:线程A修改的变量,线程B无法立即看到
原子性问题:i++操作在机器指令层面可能被中断
有序性问题:代码执行顺序与编写顺序不一致
这些问题的根源在于:
-
CPU多级缓存架构导致内存可见性问题
-
编译器/处理器优化引发指令重排序
-
线程切换带来的原子性破坏

二、JMM架构设计
2.1 内存抽象模型
JMM定义了两个核心概念:
-
主内存(Main Memory):所有线程共享的内存区域
-
工作内存(Working Memory):每个线程私有的内存副本
从上图来看,线程 1 与线程 2 之间如果要进行通信的话,必须要经历下面 2 个步骤:
- 线程 1 把本地内存中修改过的共享变量副本的值同步到主内存中去。
- 线程 2 到主存中读取对应的共享变量的值。
也就是说,JMM 为共享变量提供了可见性的保障。
不过,多线程下,对主内存中的一个共享变量进行操作有可能诱发线程安全问题。举个例子:
- 线程 1 和线程 2 分别对同一个共享变量进行操作,一个执行修改,一个执行读取。
- 线程 2 读取到的是线程 1 修改之前的值还是修改后的值并不确定,都有可能,因为线程 1 和线程 2 都是先将共享变量从主内存拷贝到对应线程的工作内存中。
2.2 内存交互协议
JMM定义了8种原子操作保证内存可见性:
操作 | 作用范围 | 说明 |
---|---|---|
lock | 主内存变量 | 标记变量为线程独占状态 |