1、计算机物理内存结构(物理内存结构决定了虚拟机内存结构)

由于处理器和主存储设备在运算速度上不上同一个数量级上,因此处理器和主存储器之间不得不增设一层高速缓存,将部分在主存储设备的运算放在高速缓存内,从而使得内存的相关运算速度跟上处理器的运算速度不至

于限制处理器的处理速度。实际工作中,处理器要操作的数据先从主存储内存内读取到高速缓存内,然后再在高速缓存内进行运算,最后再把运算的结果会写到主存储内存内。

2、虚拟机内存模型屏蔽不同物理机器的内存模型

不同的物理机器存在不同的架构,在内存处理方式上不一样,虚拟机内存模型就是屏蔽底层硬件、操作系统在内存操作上的的差异性,使得Java程序内存的访问方式具有跨平台的特性不限定于特定的底层内存访问方式。

也就是说Java虚拟机的内存模型是对底层硬件和操作系统对内存操作方式(读写访问)的抽象。(虚拟机的内存模型是对物理机内存模型虚拟)。

虚拟机内存模型根据物理机内存模型的抽象出的模型中,线程从共享内存(主内存)中读取所需要的数据,并加载到当前线程私有的内存区域(工作内存)进行运算并将运算的结果写入当前的私有线程当中,最后在将数

据同步至共享内存当中。也就是说明了为了执行线程和获取所需的数据,数据需要在线程私有的内存和共享的内存之间进行不断的交互操作。相关线程要读取数据,需要将共享内存(主内存)当中加数据加载到线程自己的私

有内存当中进行,相关线程执行业务操作需要保存数据就需要将线程私有的内存保存至主内存内。

3、缓存一致性问题

数据在私有内存和共享内存之间进行不断的交互操作,在并发的情况下,易造成数据的不一致性(共享内存和私有内存之间的缓存数据的不一致性),因而内存之间的交互操作要遵循相应的协议,内存间的交互要根据协

议进行操作。

4、Java虚拟机内存模型

(1)主内存和工作内存

主内存:主内存是公有,各个线程共享的内存,Java内存模型规定了所有变量都存储在主内存当中,对应于虚拟机内存区域内的Java堆中的对象实例部分,可以说是对物理主内存的抽象和表示。

工作内存:线程私有的, 保存了对主内存部分变量的副本,是对主内存的拷贝。对应于虚拟机内存区域内的虚拟机栈的部分区域,可以说是对物理高速缓存或者寄存器的抽象。

(2)内存间交互操作

一个变量如何从主内存拷贝至工作内存当中?又如何将工作内存的数据同步至主内存当中?主内存和工作内存之间是如何交互的?

Java虚拟机通过8个原子操作来实现主内存和工作内存之间的交互操作

内存间交互操作的准则:

(3)内存模型对volatile变量定义的特殊规则

volatile关键字:Java虚拟机提供的轻量级同步机制

volatile的两个特性:

a.volatile变量保证对所有线程的可见性(其他线程读取volatile变量的时候必须先从主内存加载到工作内存使用),final关键字和synchronized关键字也可以实现可见性

b.禁止指令重排序优化(插入内存屏障来保证处理器不发生乱序执行)

volatile在并发下是不安全的,保证volatile并发下安全的两条规则:

a.运算结果不依赖当前变量的值或者只有单一的线程修改变量值

b.变量不需要和其他状态变量共同参与不变约束

Java内存模型中对volatile变量定义的特殊规则:

a.线程对volatile变量的use操作和volatile变量的load、read动作相关联,必须连续一起出现(load_read_use)   =>      volatile变量可见性的保证,保证所有线程从主内存内加载的最新的值

b.线程对volatile变量的assign操作和store、write动作相关联,必须连续一起出现 (assign_store_write)      =>     volatile变量可见性的保证,将当强最新的值同步至主内存,保证其他线程对最新纸的可见性

c.如果线程A对volatile变量的use或assign操作先于其他线程的use或assign则,线程A对该线程的load或者store操作必定先于其他线程的load或者store操作   =>禁止指令的重排序优化

(4)long和double的非原子性协定

虚拟机允许不保证64位数据类型的load、store、 read、write 4个操作的原子性,但是商用虚拟机都选择把64位数据的读写操作作为原子操作。

(5)内存模型的3个特性

a.原子性:虚拟机模型通过内存间原子性的交互操作来保证内存的访问操作即使在并发操作仍是安全的

b.可见性:规定相关原子性操作的组合来实现变量值在所有线程间的可见性

c.有序性:通过禁止指令重排序优化,来达到代码执行的有序性

( 6)先行发生原则:判断数据是否存在竞争、线程是否安全的主要依据

对于先行发生的操作,虚拟机不进行重排序。

Java内存模型内默认不重排序的情况(天然的先天发生):

a、程序次序规则:程序代码本身的次序的先天发生,代码前面的操作先于后面代码的操作

b.管程锁定规则:同一个锁的lock操作必定先于unlock操作

c.volatile变量规则:volatile变量的写操作必定先于该变量的读操作(volatile变量的可见性保证)

d.线程启动规则:线程的启动方法start()必定先于线程的其他任何操作

e.线程终止规则:线程的终止检测必定晚于线程的任何操作

f.线程中断规则:线程的interrupt中断方法必定先去线程中断事件检测方法的

g.对象终结规则:对象的初始化操作必定先于对象的finalize()

h.传递性规则:线程先行发生的传递性

重读《深入理解Java虚拟机》七、探究Java内存模型的更多相关文章

  1. Java虚拟机解析篇之---内存模型

    今天闲来无事来,看一下Java中的内存模型和垃圾回收机制的原理.关于这个方面的知识,网上已经有非常多现成的资料能够供我们參考,可是知识还是比較杂的,在这部分知识点中有一本书不得不推荐:<深入理解 ...

  2. 深入理解java虚拟机(6)---内存模型与线程 & Volatile

    其实关于线程的使用,之前已经写过博客讲解过这部分的内容: http://www.cnblogs.com/deman/category/621531.html JVM里面关于多线程的部分,主要是多线程是 ...

  3. 深入理解Java虚拟机读书笔记8----Java内存模型与线程

    八 Java内存模型与线程   1 Java内存模型     ---主要目标:定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节.     ---此处的变量和J ...

  4. 深入理解Java虚拟机(七)——类文件结构

    Java的无关性 由于计算机领域中有很多操作系统和硬件平台同时在竞争,所以,很多编程语言的程序设计会与其运行的平台和操作系统产生耦合,这样就大大增加了程序员的工作,为了适应不同的平台,需要修改很多代码 ...

  5. 《深入理解 Java 虚拟机》学习 -- Java 内存模型

    <深入理解 Java 虚拟机>学习 -- Java 内存模型 1. 区别 这里要和 JVM 内存模型区分开来: JVM 内存模型是指 JVM 内存分区 Java 内存模型(JMM)是指一种 ...

  6. 《深入理解 Java 虚拟机》学习笔记 -- 内存区域

    <深入理解 Java 虚拟机>学习笔记 -- 内存区域 运行时数据区域 主要分为 6 部分: 程序计数器 虚拟机栈 本地方法栈 Java 堆 方法区 如图所示: 1. 程序计数器(线程私有 ...

  7. 深入理解Java虚拟机之图解Java内存区域与内存溢出异常

    Java内存区域与内存溢出异常 运行时数据区域 程序计数器 用于记录从内存执行的下一条指令的地址,线程私有的一小块内存,也是唯一不会报出OOM异常的区域 Java虚拟机栈 Java虚拟机栈(Java ...

  8. 深入理解Java虚拟机(一)、Java内存区域与内存溢出异常

    Java虚拟机所管理的内存包括以下几个运行时数据区: 程序计数器(PCR): 1.是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器 2.为线程私有 3.执行Java方法有PCR,执行 ...

  9. 【深入理解JAVA虚拟机】第二部分.内存自动管理机制.1.内存区域

    1.内存区域 根据<Java虚拟机规范(Java SE 7版)> 的规定,Java虚拟机所管理的内存将会包括以下几个运行时数据区域,如图所示.  程序计数器 当前线程所执行的字节码的行号指 ...

  10. 深入理解java虚拟机读书笔记1--java内存区域

    Java在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途.创建和销毁的时间,有一些是随虚拟机的启动而创建,随虚拟机的退出而销毁,有些则是与线程一一对应,随 ...

随机推荐

  1. 奋斗STM32V3版ADC例程

    https://wenku.baidu.com/view/a60b2042c850ad02de8041b7.html

  2. 树莓派做路由器_配置防火墙filter和nat转发_转载

    转自:https://blog.csdn.net/hustsselbj/article/details/45866681 如果用树莓派当作路由器转发有线和无线网络,则需要对iptables进行相关配置 ...

  3. 解决:android源码同步repo sync 时出现的fatal:duplicate path错误

    问题重现: 解决方法: 1.删除android项目里隐藏的 .repo 文件夹中除了以下几个文件夹的其他文件及文件夹 2.重新初始化android项目 repo init -u https//gith ...

  4. Socket 相关资料(随笔)

    由于项目上的 http 请求量较大,项目上性能跟不上.于是考虑把 短连接的 http 换成 长连接的tcp 形式 试试效果. 先 研究了一下 长连接方式.就是要用到 socket 方面的知识. pac ...

  5. 二叉树转换成森林&amp;森林变成二叉树

    一,树转换成二叉树 1,将全部兄弟结点连起来; 2,保留第一个兄弟结点与父节点的连接,断开其它兄弟结点与父节点的连接,然后以根节点为轴依照顺时针方向旋转45度 watermark/2/text/aHR ...

  6. 关于tomcat的session问题

    因为有需要每一个项目有独立端口,并且能够单独启动和关闭,所以在一台服务器上配置了多个tomcat.tomcat是完全一样的,只是各自的端口不一致. 现在的问题是单独启动一个tomcat完全没有问题. ...

  7. 转:Python语言编程学习资料(电子书+视频教程)下载汇总

    开发工具: Python语言集成开发环境 Wingware WingIDE Professional v3.2.12 Python语言集成开发环境 Wingware WingIDE Professio ...

  8. [Converge] Batch Normalisation

    参考:https://www.zhihu.com/question/38102762 参考:CNN和RNN中如何引入BatchNorm 论文:Batch Normalization: Accelera ...

  9. [AWS] Deploy react project on EC2

    如何在aws部署项目 申请到亚马逊AWS免费账户后,我们可以拥有很多的免费云服务产品项目,其中包括: EC2云服务器. Amazon S3存储. Amazon RDS数据库. Amazon Cloud ...

  10. luanet更名为distri.lua

    为了更好的体现luanet的设计意图和避免与网上另一个开源项目重名造成混淆, luanet正式更名为distri.lua.后需开发工作包括跨平台,日志,通过Fork创建新线程正在开发中. 新地址:ht ...