java内存模型的基础

两个关键问题

线程间如何通信和线程间如何同步

java内存模型的抽象结构

在java中,所有的实例域,静态域个数组元素都存储在堆内存中,堆内存在线程间共享。
java线程之间通信由Java内存模型(JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。

抽象示意图:

线程A与线程B通信要经历2个步骤
线程A把本地内存A中更新过的共享变量刷新到主内存中去。
线程B到主内存中去读取线程A之前已经跟新过的共享变量。

从源代码到指令序列的重排序

1属于编译器重排序,2、3属于处理器重排序
对于处理器重排序,JMM的处理器重排序规则会要求java编译器在生成指令序列时,插入特定类型的内存屏障指令,通过内存屏障指令来禁止特定类型的处理器重排序。

内存屏障分类:

  • LoadLoad Barriers
  • StoreStore Barriers
  • LoadStore Barriers
  • StoreLoad Barriers

    happens-before简介

  • 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作,

  • 监视器规则:对于一个锁的解锁,happens-before后随后对这个锁的加锁
  • volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读
  • 传递性:A happens-before B,B happens-before C,那么 A happens-before C

重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。

内存模型

数据依赖性

数据依赖性针对的是单个处理器中执行的的指令序列和单个线程中执行的操作。不同处理器之间和不同线程之间的数据依赖性不会被编译器和处理器考虑

as-if-serial语义

as-if-serial语义的意思是:不管怎么重排序,程序执行结果都不能改变。

重排序对多线程的影响

多线程中,对存在控制依赖的操作重排序,可能会改变程序的执行结果