1. 引言

考虑到计算机组成的内容:

原始的计算机是CPU用于计算+硬盘用于存储,由于CPU的高速发展和硬盘的缓慢发展,高速的存储需要持续供电且价格昂贵,于是引入了由高速存储组成的内存作为中间的缓冲层。形成了CPU-RAM-Main Memory的金字塔结构。

接下来,由于CPU的继续发展,内存也渐渐跟不上CPU的速度,于是引入了更小更高速的cache作为CPU和内存的缓冲。形成了我们现在熟悉的计算机组成金字塔结构。

然后,由于CPU从单核发展成了多核,计算机从单处理器发展为多处理器,而每个处理器都有自己的cache,而这些高速缓存又要共享同一个主存。为了保证多个缓存中的数据一致性,诞生了很多协议,形成了如下结构。

2. Java内存模型

此时,线程引擎控制着多个线程,就如同实际计算机的多个CPU一样,每个线程有自己的工作内存,而他们最终共享同一个主存。

这里的主存,工作内存与JVM中的堆,栈,方法区不是同一层次内存划分。

3. 内存间的交互操作

Java内存模型定义了八种操作来完成内存与工作内存的具体交互协议:

  • lock 锁定,作用于主内存的变量,把一个变量标识为一个线程独占状态。
  • unlock 解锁,作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
  • read 读取,作用于主内存的变量,把一个变量从主内存传入现成的工作内存中。
  • load 载入,作用于工作内存的变量,把通过read从主内存中得到的变量放入工作内存的变量副本中。
  • use 使用,作用与工作内存的变量,把工作内存中一个变量传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个动作。
  • assign 赋值,作用于工作内存的变量,把执行引擎中获得的值赋给工作内存中的一个变量,每当虚拟机遇到一个给变量赋值的字节码指令时会执行这个动作。
  • store 存储,作用于工作内存的变量,把工作内存中的一个变量值传到主内寸中。
  • write 写入,作用于主内存的变量,把通过store从工作内存中得到的变量的值传送到主内存的变量中。

用流程图表示交互操作如下:

如果把一个变量从主存复制到工作内存,就需要按顺序的执行read和load操作。

如果把一个变量从工作内存复制到主存,就需要按顺序的执行store和write操作。

Java内存只要求必须按上述顺序执行操作,没有要求保证操作连续。

Java还规定上述8种操作必须符合如下七条规定:

  1. 不允许read-load,store-write这两对操作的操作之一单独出现。
  2. 不允许一个线程丢弃他的最近assign操作,即一个工作内存中的最终变量必须同步到主内存中。
  3. 在没有发生任何assign操作时,不允许一个线程把工作内存中的变量同步到主内存中。(不允许无原因同步)
  4. 一个新变量只能在主内存中产生,不允许工作内存直接使用一个未被load或者assign的变量。换言之,执行use前必须load,执行store前必须assign。
  5. 一个变量同时只允许一个线程对其执行lock操作,lock和unlock必须成对出现。
  6. 如果一个变量事先没有被执行lock操作,则不能执行unlock操作,也不允许去unlock其他线程的lock操作。
  7. 一个变量执行unlock前,必须把此变量同步到主内存中,即执行store和write操作。

    四. 重排序

由上知八种操作没有连续性要求,但是很多操作是其他操作的前提,操作间满足一定的先序排列。因此,在编译器对代码优化时,往往会通过重排序来优化执行效率。

重排序分为三种类型:

  1. 编译器优化的重排序

    编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。

  2. 指令集并行的重排序

    现代处理器采用指令集并行技术将多条指令重叠执行,如果不存在数据依赖,处理器可以改变语句对应机器指令的执行顺序。

  3. 内存系统的重排序

    由于处理器使用缓存和读写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

从执行到重排序过程如下:

为了保证内存的可见性,Java编译器在生成指令序列的适当位置会插入内存屏障来禁止特定类型的处理器重排序,内存屏障分为以下四种:

  • LoadLoad
  • LoadStore
  • StoreLoad
  • StoreStore

参考文章

残雪余香-Java内存模型

深入理解JVM——JVM内存模型

Java基础:内存模型的更多相关文章

  1. 全网最硬核 Java 新内存模型解析与实验单篇版(不断更新QA中)

    个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...

  2. java线程内存模型,线程、工作内存、主内存

    转自:http://rainyear.iteye.com/blog/1734311 java线程内存模型 线程.工作内存.主内存三者之间的交互关系图: key edeas 所有线程共享主内存 每个线程 ...

  3. Java虚拟机内存模型及垃圾回收监控调优

    Java虚拟机内存模型及垃圾回收监控调优 如果你想理解Java垃圾回收如果工作,那么理解JVM的内存模型就显的非常重要.今天我们就来看看JVM内存的各不同部分及如果监控和实现垃圾回收调优. JVM内存 ...

  4. java String 内存模型

    关于java的内存模型,参照以下的一篇文章: https://isudox.com/2016/06/22/memory-model-of-string-in-java-language/

  5. Java虚拟机--内存模型与线程

    Java虚拟机--内存模型与线程 高速缓存:处理器要与内存交互,如读取.存储运算结果,而计算机的存储设备和处理器的运算速度差异巨大,所以加入一层读写速度和处理器接近的高速缓存来作为内存和处理器之间的缓 ...

  6. 掌握Java的内存模型,你就是解决并发问题最靓的仔

    摘要:如果编写的并发程序出现问题时,很难通过调试来解决相应的问题,此时,需要一行行的检查代码,这个时候,如果充分理解并掌握了Java的内存模型,你就能够很快分析并定位出问题所在. 本文分享自华为云社区 ...

  7. Java对象内存模型

    2 Java对象内存模型 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header). 实例数据(Instance Data)和对齐填充(Padding). 在 JVM ...

  8. Java线程内存模型-JVM-底层原理

    public class Demo1 { private static boolean initFlag=false; public static void main(String[] args) t ...

  9. Java虚拟机 - 内存模型

    本文主要介绍Java虚拟机的内存分布以及对象的创建过程. 一.Java虚拟机的内存分布 文章开始前读者需要了解Java虚拟机的运行时数据区是怎样划分的.如下图所示: 1.程序计数器(Program C ...

  10. Java的内存模型

    "让计算机并发执行若干个运算任务"与"更充分地利用计算机处理器的效能"之间的因果关系,看起来顺理成章,实际上它们之间的关系并没有想象中的那么简单,其中一个重要的 ...

随机推荐

  1. Android反编译获取资源文件-android学习之旅(69)

    有时候你看到一些很好看的布局,会考虑别人怎么实现的,回想参考一下,那么这时候反编译一下是很必要的. 要用到的工具apktool.bat和aapt.exe和apktool.jar(要最新版本) 下载前两 ...

  2. C++ Primer 有感(函数)

    1.函数应该在头文件中声明,并在源文件中定义.(定义函数的源文件应包含声明该函数的头文件)将提供函数声明的头文件包含在定义该函数的源文件中,可使编译器能检查该函数的定义和声明是否一致. 2.既可以在函 ...

  3. iOS9关键字的简单使用

    在iOS 9 苹果推出了很多关键字, 目的其实很明确, 主要就是提高开发人员的效率, 有益于程序员之间的沟通与交流, 在开发中代码更加规范! 1. nullable 与 nonnull nullabl ...

  4. How To Transact Move Order Using INV_PICK_WAVE_PICK_CONFIRM_PUB.Pick_Confirm API

    In this Document Goal   Solution   Sample Code:   Steps:   FAQ   References APPLIES TO: Oracle Inven ...

  5. C#之结尾篇

    在Top10语言中,C#是最优美的语言,没有之一,在Top10语言中,C#所可用的标准库及可获得其他库是最强大的之一,这个必须带上之一,因为有java在,在Top语言中,C#语言是性能最高的语言之一, ...

  6. Android 数据库框架ormlite

    Android 数据库框架ormlite 使用精要 前言 本篇博客记录一下笔者在实际开发中使用到的一个数据库框架,这个可以让我们快速实现数据库操作,避免频繁手写sql,提高我们的开发效率,减少出错的机 ...

  7. C++大小写转换和性能

    p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; f ...

  8. 解决unbuntu14.04上的eclipse自动退出的问题

    新安装的ubuntu14.04版,把以前12.04上正常使用的eclipse拷贝到14.04上后,启动eclipse后,输入代码时出现点"."提示符就会自动重启. jdk是1.7. ...

  9. This version of the rendering library is more recent than your version of ADT plug-in. Please update

    预览layout.xml文件时提示: This version of the rendering library is more recent than your version of ADT plu ...

  10. 使用Material Design Tint和视图详解

    视图 首先来讲Material Design 视图的概念,在新的api中,新添加了z轴的概念,z轴垂直于屏幕,用来表现元素的层叠关系,z值(海拔高度)越高,元素离界面底层(水平面)越远,投影越重,这里 ...