当前位置: 首页 > news >正文

深入解析JMM原理

如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想!

架构殿堂

概念

​ Java内存模型(Java Memory Model,JMM)JMM主要是为了规定了线程和内存之间的一些关系。根据JMM的设计,系统存在一个主内存(Main Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。

特性

原子性

指一个操作是不可中断的,即使是多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰

可见性

指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。显然,对于串行程序来说,可见性问题 是不存在。因为你在任何一个操作步骤中修改某个变量,那么在后续的步骤中,读取这个变量的值,一定是修改后的新值。但是这个问题在并行程序中就不见得了。如果一个线程修改了某一个全局变量,那么其他线程未必可以马上知道这个改动。

有序性

对于一个线程的执行代码而言,我们总是习惯地认为代码的执行时从先往后,依次执行的。这样的理解也不能说完全错误,因为就一个线程而言,确实会这样。但是在并发时,程序的执行可能就会出现乱序。给人直观的感觉就是:写在前面的代码,会在后面执行。有序性问题的原因是因为程序在执行时,可能会进行指令重排,重排后的指令与原指令的顺序未必一致

主内存与工作内存

处理器上的寄存器的读写的速度比内存快几个数量级,为了解决这种速度矛盾,在它们之间加入了高速缓存。

加入高速缓存带来了一个新的问题:缓存一致性。如果多个缓存共享同一块主内存区域,那么多个缓存的数据可能会不一致,需要一些协议来解决这个问题。

在这里插入图片描述

所有的变量都 存储在主内存中,每个线程还有自己的工作内存 ,工作内存存储在高速缓存或者寄存器中,保存了该线程使用的变量的主内存副本拷贝。

线程只能直接操作工作内存中的变量,不同线程之间的变量值传递需要通过主内存来完成。
在这里插入图片描述

数据存储类型以及操作方式

  • 方法中的基本类型本地变量将直接存储在工作内存的栈帧结构中;
  • 引用类型的本地变量:引用存储在工作内存,实际存储在主内存;
  • 成员变量、静态变量、类信息均会被存储在主内存中;
  • 主内存共享的方式是线程各拷贝一份数据到工作内存中,操作完成后就刷新到主内存中。

内存间交互

关于主内存与工作内存之间的具体交互协议,即一个变量如何从主内存拷贝到工作内存,如何从工作内存同步回主内存子类的细节实现,java内存模型定义了八种操作:(这八个操作都具有原子性)

lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占的状态。

unclock(解锁):作用于主内存的变量,把一个处于锁定的状态释放出来。

read(读取):作用于主内存的变量,把一个变量的值从主内存传输到线程的工作内存中

load(载入):作用于工作内存的变量,把read操作从主内存 得到的变量值放入工作内存的变量副本中。

use(使用):作用于工作内存的变量,把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的                             值的字节码指令时将会执行这个操作。

assign(赋值):作用于工作内存的变量,把一个从执行引擎接收到的值 赋值给工作内存的变量,每当虚拟机遇到一个给变                             量赋值的字节码指令时执行这个操作。

store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传递到主内存,以便write操作使用。

write(写入):作用于主内存的变量,把store操作从工作内存中得到的变量的值放入主内存的变量中。

如图:

在这里插入图片描述

指令重排序的条件

  • 在单线程环境下不能改变程序的运行结果;
  • 存在数据依赖关系的不允许重排序;
  • 无法通过Happens-before原则推到出来的,才能进行指令的重排序。

happens-before 原则

  • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
  • 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
  • volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
  • 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始

jvm和jmm之间的关系

jmm中的主内存、工作内存与jvm中的Java堆、栈、方法区等并不是同一个层次的内存划分,这两者基本上是没有关系的,如果两者一定要勉强对应起来,那从变量、主内存、工作内存的定义来看,主内存主要对应于Java堆中的对象实例数据部分,而工作内存则对应于虚拟机栈中的部分区域。

从更低层次上说,主内存就直接对应于物理硬件的内存,而为了获取更好的运行速度,虚拟机(甚至是硬件系统本身的优化措施)可能会让工作内存优先存储于寄存器和高速缓存中,因为程序运行时主要访问读写的是工作内存。

如果大家对java架构相关感兴趣,可以关注下面公众号,会持续更新java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达, 超神之路从此展开, BTAJ不再是梦想!

架构殿堂

相关文章:

  • 为Redmine的项目加上起止时间
  • 详尽Netty(一):初探netty
  • Php基础知识测试题
  • 设计模式(四):建造者模式的详细解析
  • [swust1745] 餐巾计划问题(费用流)
  • 详尽Netty(二):源码环境搭建
  • AssetBundle管理机制(上)
  • 详尽Netty(三):Channel
  • 循序渐进之Spring AOP(5) - 创建切面
  • 牛逼!阿里推出国产开源的jdk! 快来试试吧!
  • ES6 中的let 声明变量
  • 原来Java类的加载过程是这样的?
  • 淘宝数据库OceanBase SQL编译器部分 源代码阅读--生成物理查询计划
  • 聊聊jvm几种垃圾收集器
  • 搭建 webpack + React 开发环境
  • 【5+】跨webview多页面 触发事件(二)
  • AngularJS指令开发(1)——参数详解
  • CEF与代理
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • javascript面向对象之创建对象
  • JS实现简单的MVC模式开发小游戏
  • magento 货币换算
  • SwizzleMethod 黑魔法
  • vuex 学习笔记 01
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 不上全站https的网站你们就等着被恶心死吧
  • 后端_ThinkPHP5
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 智能网联汽车信息安全
  • (04)odoo视图操作
  • (39)STM32——FLASH闪存
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (Python第六天)文件处理
  • (大众金融)SQL server面试题(1)-总销售量最少的3个型号的车及其总销售量
  • (十三)Flask之特殊装饰器详解
  • (十五)使用Nexus创建Maven私服
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (转)iOS字体
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • .bat批处理(三):变量声明、设置、拼接、截取
  • .net(C#)中String.Format如何使用
  • .net网站发布-允许更新此预编译站点
  • .Net语言中的StringBuilder:入门到精通
  • [ HTML + CSS + Javascript ] 复盘尝试制作 2048 小游戏时遇到的问题
  • [<死锁专题>]
  • [Android]使用Git将项目提交到GitHub
  • [autojs]逍遥模拟器和vscode对接
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [C]整形提升(转载)
  • [C语言][PTA基础C基础题目集] strtok 函数的理解与应用
  • [echarts] y轴不显示0
  • [elastic 8.x]java客户端连接elasticsearch与操作索引与文档
  • [ffmpeg] aac 音频编码