Java内存模型一(基础)
- Java内存模型的基础:主要介绍内存模型相关的基本概念
- Java内存模型中的顺序一致性:主要介绍 重排序 与 顺序一致性内存模型
- 同步原语:主要介绍3个同步原语 (synchronized、volatile、final) 的内存语义及重排序规则在处理器中的实现
- Java内存模型的设计:主要介绍Java内存模型的设计原理,及其余处理器内存模型和顺序一致性内存模型的关系
1、并发编程模型的两个关键问题
在命令式编程中,线程之间的通信机制有两种:共享内存、消息传递
线程之间如何通信
通信:指线程之间以何种机制来交换信息。
- 共享内存 并发模型中:线程间共享程序的公共状态,通过读 - 写内存中的公共状态进行隐式通信。
- 消息传递 并发模型中:线程间没有公共状态,必须通过发生消息来显式进行通信。
线程之间如何同步
同步:指程序中用于控制不同线程间操作发生的相对顺序的机制。
- **共享内存 **并发模型中:同步是显式进行的。程序员必须显式指定代码需要在线程间互斥执行。
- **消息传递 **并发模型中:由于消息的发送必须在消息的接受之前,因此同步是隐式进行的。
Java的并发采用的是共享内存模型
Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。
2、Java内存模型(JMM)的抽象结构
- 共享变量(所有实例域、静态域、数组元素)都存储在堆内存中,堆内存在线程之间共享。
- 局部变量、方法定义参数、异常处理器参数,不会在线程之间共享,也不会有内存可见性问题,不受内存模型影响。
JMM决定一个线程对共享变量的写入何时对另一个线程可见。
JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中;每个线程都有一个私有的本地内存,本地内存中存储了该线程以读-写共享变量的副本。
JMM通过控制主内存与每个线程的本地内存之间的交互,来保证Java的内存可见性。
3、从源代码到指令序列的重排序
重排序分为3种:
- 编译器优化重排序:属于编译器重排序
- 指令级并行重排序:属于处理器重排序
- 内存系统重排序:属于处理器重排序
编译Java源代码经历的重排序顺序:Java源代码 -> 编译器优化重排序 -> 指令级并行重排序 -> 内存系统重排序 -> 最终执行的指令序列
防止重排序可能导致多线程内存可见性问题
- 对于编译器重排序:JMM的编译器重排序规则会禁止特定类型的编译器重排序(非所有编译器重排序都要禁止)。
- 对于处理器重排序:JMM的处理器重排序规则会要求Java编译器在生成指令序列时,插入特定类型的内存屏障,来禁止特定类型的处理器重排序。
JMM属于语言级别的内存模型,它保证不同的编译器和不同的处理器平台上,通过禁止特定类型的编译器重排序和处理器重排序,提供一致的内存可见性保证。
4、内存屏障的分类
内存屏障类型表:
屏障类型 | 指令实例 | 说明 |
---|---|---|
LoadLoad Barriers | Load1;LoadLoad;Load2 | 确保Load1数据的装载先于Load2及所有后续装载指令的装载 |
StoreStore Barriers | Store1;StoreStore;Store2 | 确保Store1数据对其他处理器可见先于Load2及所有后续存储指令的存储 |
LoadStore Barriers | Load1;LoadStore;Store | 确保Load1数据的装载先于Store2及所有后续存储指令刷新到内存 |
StoreLoad Barriers | Store1;StoreLoad;Load2 | 确保Store1数据对其他处理器变得可见,先于Load2及所有后续存储指令的存储 |
StoreLoad Barriers 是一个“全能型”的屏障,此指令会使该屏障之前的所有内存访问指令完成之后,才执行该屏障之后的内存访问指令。因此执行该屏障的开销会很昂贵。
5、happens-before
JSS-133内存模型使用 happens-before 的概念来阐述操作之间的内存可见性。
如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在 happens-before 关系。
happens-before规则:
- 程序顺序规则:一个线程中的每个操作,happens-before 于该线程中任意后续操作。
- 监视器锁规则:对一个锁的解锁,happens-before 于随后对这个锁的加锁。
- volatile变量规则:对一个 volatile 域的写,happens-before 于任意后续对这个 volatile 域的读。
- 传递性规则:如果 A happens-before B,且 B happens-before C,那么 A happens-before C。
Java内存模型一(基础)
https://cuilan.github.io/2019/05/22/并发编程/java内存模型一/