JMM

2018-08-02  本文已影响0人  kindol

JVM规范了视图定义一种JMM来屏蔽各个硬件平台和OS的内存访问差异,属于语言级的内存模型,实现让Java程序在各平台下都能达到一致的内存访问效果,通过禁止特定类型的编译器重排序和处理器重排序,为程序员提供一致的内存可见性保证

JMM定义了什么东西?

JMM定义了程序中的变量访问规则(程序执行的次序),但是,为了更好的执行性能,JMM没有限制执行引擎使用缓存,也没有限制编译器对指令进行重排序,即,在JMM中,会存在缓存一致性问题和指令重排序问题

JMM规定所有的变量都在主存中,每个线程有自己的工作内存,线程对变量的所有操作都必须在工作内存中进行,而不能直接对主存进行操作,并且每个线程不能直接访问其他线程的工作内存。

一些概念

3个特性

JMM定义线程和主寸的抽象关系

线程的共享变量存在主存中,每个线程有一个私有的本地内存,本地内存存储了该线程以读/写共享变量的副本。

t2.png

如果线程A与线程B之间要通信的话,必须要经历下面2个步骤。

  1. 线程A把本地内存A中更新过的共享变量刷新到主内存中去
  2. 线程B到主内存中去读取线程A之前已更新过的共享变量

指令重排序

执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。重排序分3种类型。

t3.png

1为编译器重排序,2和3为处理器重排序。重排序会涉及内存可见性问题

对于编译器,JMM的编译器重排序规则会禁止特定类型的编译器重排序(不是所有的编译器重排序都要禁止)。

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

t5.png

happens-before原则:

happens-before规则对应一个或多个编译器和处理器重排序规则。如果一个操作的执行结果对另一个操作可见,那么这两个操作必须要存在happens-before关系(两个操作可以是位于一个线程或不同线程)

未同步程序的执行特性

对于未同步的多线程程序,JVM提供最小的安全性:设置默认值(0,Null,false),因而JVM在分配对象申请空间之后,会先将空间进行清零。

未同步程序整体是无序的,和顺序一致模型有如下差异:

  1. 不保证单线程内的操作按照程序顺序执行
  2. 不保证所有线程看到一致的操作执行顺序
  3. 不保证对64位的long型和double型变量的写操作具有原子性(在JSR-133之前的就内存模型中,对64位的long型和double型变量的读/写操作可以被拆分成两个32位的读/写操作来执行,之后进允许把一个64位的long型和double型变量的写操作可以被拆分成两个32位的写操作来执行,任意读操作都必须具有原子性)

参考:

《java并发编程的艺术》
上一篇 下一篇

猜你喜欢

热点阅读