Java内存模型的深层理论

本文部份内容选自<<深刻理解Java虚拟机>> 以及 CrazyDailyQuestion的ArtarisCNgit

引言

  Java 内存模型 , 即 Java Memory Model,JMM 来屏蔽各类硬件和操做系统的内存访问差别,以实现让Java 在各类平台都达到一致的访问效果.Java 内存模型规范了 JVM 如何 禁用缓存编译优化 的方法.github

一.Main Memory和Working Memory

  • Java 规定全部的变量都存储在主内存(Main Memory)中
  • 每条线程Working Memory 保存了该Thread使用的变量的Main Memory副本copy
    • Thread间变量值经过 Main Memory 传递
    • Thread对变量操做(赋值,读取)只能在 Working Memory 进行, Main Memory 不可读
    • ThreadA 没法 直接 访问 ThreadB Working Memory 变量,同理ThreadB也是如此

下面我就用图文并茂的方式给你们展现一下: Thread,Main Memory和Working Memory的交互关系缓存

二.内存间交互操做

那么,变量是如何经过Main Memory copy给 Working Memory,如何从 Work Memory sync 到 Main Memory的呢?安全

jvm实现必须保证每一种操做都是原子的,不可细分的(double 和 long比较特殊)并发

Java 提出了 8种操做类型app

变量做用域: Main Memoryjvm

方法 做用
lock(🔒) 把Thread 设置线程独有 Tag
unlock(🔓) 释放变量,给其余Thread使用
read(读取) 变量从Main Memory传输到Thread 的 Working Memory途径

变量做用域: Working Memory优化

方法 做用
load(载入) 变量值放到Working Memory 的变量副本中
use(使用) Working Memory的变量值传给执行引擎,JVM收到须要执行的变量的字节码指令时候,会执行这个操做
assign(赋值) 他把一个从执行引擎接收的值赋给Working Memory 的变量,JVM收到须要执行的变量的字节码指令时候,会执行这个操做
store(存储) 把变量值传给 Main Memory

变量做用域: Main Memorythis

方法 做用
write(写入) Working Memory的变量放到Main Memory中

操做规则:操作系统

  太官方,主要是为了解决Java并发安全,Android用的不太多,只想理清流程,不想看细节~

三.volatile

  没有被volatile位数据能够分割为两个32位进行操做,volatile和syhnronized功能相似,解决多Thread竞争问题

操做规则:

  • 保证变量对多有Thread的可见性
    • 变量值被修改,Thread能当即感知这个值
    • 在切换线程时候,变量可能被重定义,却来不及更新建议用 volatile,可是 volatile 并不能完美解决线程安全问题,只能作变量提早预判,此时得采用acomic或者syhnronized等其余方式

四.long和double

  long 和 double 具备非原子性,不须要用考虑使用volatile修饰

五.原子性,可见性,有序性

  • 原子性: 除了 long 和 double之外的基本数据类型都具备原子性

  • 可见性: 当一个线程修改了这个值,其余线程可以当即感知,即 Main Memory 传递的方式具备可见性

    • volatile 能保证新值能当即同步到 Main Memory,以及每次使用 从 Main Memory 当即 refresh.

    • final 字段在constrctor方法 init 后,constrctor 没有把 "this" 引用传递出去(this 逃逸很是危险),那么在其余线程中就能看见 final 字段的值

    • synchronized 变量在同步代码块,unlock以后,必须回到 Main Memory,执行完write操做

  • 有序性:

    • 本线程中全部操做都是有序的(Whithin-thread As-if-Serial Semantics)

    • ThreadA watch ThreadB 都是无序的(指令重排,Main Memory与Working Memory 同步 延迟)

      • volatile 禁止指令重排

      • synchronized 一个变量 一个时刻只容许一条线程进行lock

六.happen-before

  • 程序次序规则

      在一个程序里面,按照程序代码顺序,书写在前面的操做happen-before发生书写在后面的操做

  • 管程锁定规则

      同一把锁,unlock happen-before lock 操做

  • 线程中断原则

  Thread.intercupt()方法检测到是否中断发生

  • 传递性

  Happens-Before 具备传递性,若是 A Happens-Before B,B Happens-Before C,则 A Happens-Before C

  • 对象终结规则

  对象 init happen-before finalize()

七.问题致使缘由

  • 缓存致使的可见性问题
  • 切换线程致使的原子性问题
  • 编译优化带来的有序性问题「指令重排」
相关文章
相关标签/搜索