本文主要说明两个问题:JMM存在的意义是什么?JMM内部的工作原理是什么(重点讲一下并发编程模式下的数据访问一致性问题) 。

1.为什么要使用JMM?

当我们刚开始接触JAVA语言的时候,就会被告知JAVA程序是可以实现跨平台运行的(即同一份代码资源可运行在不同的硬件配置下,不同的操作系统下)。那么JAVA 是如何在不同的硬件和操作系统内存访问方式存在差异的情况下,实现 同一个Java 程序在各种平台下的运行结果都相同(达到一致的内存访问效果)的呢。靠的就是神奇的JMM。

在这里要牢记两个事实:

(1)我们平时所写的每一行程序代码其实就是对计算机发出的一个操作指令,而这些指令的运行空间是CPU。

(2)程序中不可避免的会涉及到对变量和临时数据的读取与写入。而这些变量和临时数据是存储在物理内存memory中的。

而CPU和内存两者之间存在一个很明显的速度不匹配问题:

CPU 执行速度很快,而从内存读取数据和向内存写入数据的过程跟 CPU 执行指令的速度比起来要差几个数量级,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的速度。

为解决该矛盾,人们便在CPU和内存之间增加了高速缓存cache,如下图所示:

增加了cache后,程序的执行过程就变为:

(1)将运算需要的数据从主存复制一份到CPU的高速缓存当中

(2)CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据

(3)运算结束之后,再将高速缓存中的数据刷新到主存当中。

事实上,CPU上可能同时开多个线程,多个线程对同一份数据进行访问,很容易出现数据访问不一致的问题。如何保证数据访问的一致性是我们JMM要解决的关键问题。

2.JMM的内部工作机制

java内存模型和jvm内存模型是不一样,要区分开。如上图所示,多个线程对共享变量并没有直接采用加锁的方式,其中

(1)实际内存(也叫主内存)中存储的是待共享的变量值。

(2)CPU中每个线程可以保留共享变量的副本。其中保存共享副本的地方称为每一个线程的工作内存threadLocal。每一个线程只能直接操作对应工作内存中的变量。

而不同线程之间的变量值传递则需要通过主内存(memory)来完成。如何保证主内存和线程工作内存的数据一致性,是我们需要重点关注的地方:

事实上,JMM中使用volatile关键字保证主内存和线程工作内存的数据一致性.

其工作原理大致如下:

(1)线程A的工作内存中的变量一旦发生了变化,就会有监视器检测到该变化。

(2)检测器通知CPU将该变化值刷新到内存。

(3)其他线程B/C..,在使用同一个变量时,为保证访问到的数据确实是线程A修改过的新数据,其采用的是CAS乐观锁策略(简单理解就是,永远以主存中的内容为参考)。即,

1)拿自己工作内存中的变量值和主存中的变量值比较

2)如果相等,则使用工作内存threadLocal里的变量

3)如果不相等,则用主内存的变量替换本地的变量

而JMM的性能问题,则是通过指令重排的方式保证。

java内存图解_图解JAVA内存模型(JMM:JAVA Memory Model)相关推荐

  1. gtk 控件内存回收_咱们从头到尾说一次 Java 垃圾回收

    作者:聂晓龙(花名:率鸽) 来源:微信公众号,阿里巴巴中间件 之前上学的时候有这个一个梗,说在食堂里吃饭,吃完把餐盘端走清理的,是 C++ 程序员,吃完直接就走的,是 Java 程序员. 确实,在 J ...

  2. go 是常驻内存吗_图解 Go 内存分配器

    原标题:图解 Go 内存分配器 作者 | Ankur Anand 译者 | 闫亮 内存分配器一直是性能优化的重头戏,其结构复杂.内容抽象,涉及的数据结构繁多,相信很多人都曾被它搞疯了.本文将从内存的基 ...

  3. 内存分配策略(二):JMM,Java Memory Model

    Java内存模型简述 为了屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果,Java虚拟机规范中定义了Java内存模型. Java内存模型是一种规范,它规 ...

  4. jvm内存结构_聊聊JVM内存结构

    起因 我们经常会在面试的时候被问到JVM的内存结构,很多人会觉得这东西真的有用吗?也就是面试造火箭,入职拧螺丝.问这个就是纯粹来刁难人的吧. 但实际上,我们细想一下. •假设你不知道局部变量实际上属于 ...

  5. java核心面试_前100多个核心Java面试问题

    java核心面试 Core Java interview questions help you in preparing for java based interviews. Whether you ...

  6. Java并发插件_五分钟,轻松掌握Java并发编程!

    Java作为最流行的编程语言之一,随着 Java 8的到来,越来越多的人开始学习,并深入研究!下面将介绍 Java并发编程,让开发者在最短的时间里掌握并发编程. 1. 并发 1.1. 什么是并发? 并 ...

  7. java 底层运行_从表面到底层丨Java和JVM的运行原理,现在带给你

    Java,编程语言,被创造于90年代初,在经历了这么多年的风风雨雨,Java已经成长为世界第一的编程语言,根据往期以及目前的数据来看,Java的使用频率为全球第一,即使偶尔会有第二第三的情况,但是这依 ...

  8. spark如何防止内存溢出_什么叫内存溢出?内存泄漏的定义又是什么?使用中如何避免?...

    一.基本概念 内存溢出:简单地说内存溢出就是指程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存,于是就发生了内存溢出. 内存泄漏:内存泄漏指程序运行过程中分配内存给临时变量,用 ...

  9. java性能实战_【从零单排】Java性能排查实战模拟

    当线上发生了性能问题时,需要我们快速定位问题.本文模拟了一次内存泄漏,从零教学一步步手动排查. 模拟事故现场 使用如下代码模拟内存泄漏.起了几个问题线程(在不停地创建很大的StringBuilder) ...

最新文章

  1. 通过WebViewJavascriptBridge实现OC与JS交互
  2. Java JDBC批处理插入数据操作
  3. 实现SSH密钥登陆Linux系统的方法(Linux公私钥生成)
  4. 【数据结构与算法】中缀表达式 - 后缀表达式 - 求值
  5. 非mapreduce生成Hfile,然后导入hbase当中
  6. 17年前存款11万,取款时银行以销户为由拒绝,法院判银行全额赔付
  7. 基于AWT、Swing的GUI程序 - 改变观感
  8. RadHat 6 系列心路历程、新功能及变化
  9. [linux]获取当前文件所在目录的函数
  10. python 拆分excel单元格_python 操作excel
  11. 代码的坏味道之十七 :Inappropriate Intimacy(狎昵关系)
  12. 禁用Insert按键
  13. 小姜的模拟学习日记_spectre使用
  14. portal使用常见错误
  15. 前端开发毕业设计如何选题?怎么做?
  16. USACO 刷水记录
  17. 快手小店通效果好吗?
  18. 台湾 天堂java 论坛_tiantangsifu_Rev1388jar_1386db java编写天堂私服*系统 - 下载 - 搜珍网...
  19. [搜索引擎友好之路]搜索引擎优化常见问题与回答
  20. 点点鼠标在线绘制GO/KEGG富集分析泡泡图

热门文章

  1. 测试计算机操作基础知识,计算机病毒基础知识测试
  2. 取整 除法_Python学习教程:Python3除法之真除法、截断除法和下取整对比
  3. web浏览器_vs2019使用webview2开发web浏览器 - 左正
  4. 算法与数据结构_数据结构与算法专题--算法基本概念
  5. 网络部署过程中_郑州萤火云SEO网络优化:SEO过程中的容易犯的错误
  6. C语言学习之怎样引用指针变量
  7. linux调小根目录,Linux根目录分区大小调整教程
  8. 三态门三个状态vhdl_人防门是什么?为什么会侵线导致重庆地铁事故
  9. 第8.15节 Python重写自定义类的__repr__方法
  10. Kotlin when 流程判断