Java内存模型一(基础)

  • Java内存模型的基础:主要介绍内存模型相关的基本概念
  • Java内存模型中的顺序一致性:主要介绍 重排序顺序一致性内存模型
  • 同步原语:主要介绍3个同步原语 (synchronizedvolatilefinal) 的内存语义及重排序规则在处理器中的实现
  • 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内存模型一/
作者
zhang.yan
发布于
2019年5月22日
许可协议