1.和java内存结构的区别:

很多人会把jmm和Java内存结构搞混,网上搜到的一些文章也是如此,java内存结构就是我们常说的堆,栈,方法区,程序计数器..., 当jvm虚拟机启动的时候,会初始化这些内存区域。而java内存模型是一套虚拟机规范,它遵循虚拟机规范定义了一套用于处理多线程下对数据的原子性,可见性,有序性的规则,它在每个jvm下的实现都可以是不同的,只要符合虚拟机规范就可以。

要知道java内存模型设计的意义,首先我们可以了解一下操作系统的内存模型:

2.操作系统内存模型

在最早的时候,cpu和内存直接打交道,那个时候两者速度是差不多的,但是后来随着cpu发展迅速,内存速度越来越跟不上了,cpu每次获取数据的时候就干瞪眼,于是乎就出现了高速缓存,寄存器这些玩意,但是这玩意是每个核心独有的,你其他核心访问的时候还是从你自己的寄存器-几级高速缓存-主存获取,主存是共享的,但是你总不能每次改一下,就刷一次主存,那也太慢了,没啥意义,所以你肯定得攒一段时间再写到主存,于是乎,一个共享的变量,你改了,但是还没到你要刷到主存的时候,我也改了,但是我读不到你缓存里的数据,那肯定就会出现缓存不一致的问题。

除了这种情况,cpu为了让内部的运算单元能被充分利用,可能会打乱代码顺序执行,我们听过的指令重排就是java虚拟机层面类似的优化,那么这种问题如何能解决呢其实这些就是我们所说的原子性,可见性,顺序性发生的原因,那么操作系统层面是怎么保证的呢,我总不能为了速度,不管他对不对了吧。为了解决数据一致性的问题,通常各个处理器访问缓存都遵循一些协议,主要有:MSI、MESI(Illinois Protocol)、MOSI、Synapse、Firefly 及 Dragon Protocol 等,下面我们主要介绍一下MESI:

3.MESI

  在多核处理器中,缓存都是独立的,但是多核之间需要共享数据,那么我们如何保证这些数据的一致性?

  在MESI中,每个缓存行都有4中状态:M ,E, S,I

  M: M全称Modified,它标识这行数据在本缓存被修改了,和内存中不一致,但本缓存是有效的,如果别的CPU内核要访问主存中这块数据,则该缓存行数据必须先写回主存,状态改为S

  E: 全称Exclusive,表示当前数据有效,但数据只有该缓存和主存有,当别的Cpu读时,状态改为S,如果被修改了,改为M

  S: 全称Shared,表示当前缓存行在其他缓存中也有,且自身未修改,缓存行可以被抛弃(缓存行有自己的淘汰策略)

  I: 全称invalid,表示当前缓存行是无效的。

基于上面的知识,其实可以大致知道MESI就是通过在读写数据时,通知所有拥有这块数据的核心修改自身的状态,达到在任意时刻任意核心读到的数据都是一致的,而且不需要实时更新数据到主存或其他缓存。

java内存模型和操作系统的是比较类似的,它的所有操作基本上都是对底层的映射,它定义了线程和主存之间的抽象的映射关系:

线程间共享的变量存在主存中,线程的独有的缓存存储变量的副本,其实大体上和操作系统理解起来是一个道理。

  jmm是比较抽象的一个概念,必须要结合操作系统的内存模型来结合理解,像操作系统为了提升性能,加了多级缓存,加了寄存器,并且会优化要执行的代码。而加了之后也是有代价的,那就是会造成所谓的并发三大特性:

1.可见性:就是当一个共享变量被其他线程修改后,当前线程可以立刻读到改变后的值。

为什么会出现可见性问题?

如上图所示,每个线程都有自己的本地缓存(为了效率),而本地缓存就会导致如线程2将一个共享变量变更了,刷到主存中,但线程1不知道我这个值变了,还是会去读缓存,就会导致线程2的修改对线程1不可见。

如何解决可见性问题:

1.volatile关键字

2.通过直接调用内存屏障storeFence()

3.synchronized关键字

4.Lock保证

5.final关键字

  2.有序性:

用一句通俗但又不易懂的话来说就是眼见不一定为实,怎么理解呢,jvm为了效率,有时候会对指令进行重排,它不一定会按照你写的代码一步步执行,当然有前后依赖关系的肯定不会重排。

如何解决有序性问题:

1.volatile关键字

2.通过直接调用内存屏障storeFence()

3.synchronized关键字

4.Lock保证

  3.原子性:

要么都执行,要么不执行,不管你有多少个线程同时执行,我这个原子性的操作一定是不会被打断或者拆分执行,相当于是这个操作以及不能再被拆分了。

如何保证原子性:

1.CAS的方式

2.synchronized关键字

3.Lock保证

本章节主要介绍了操作系统内存模型的设计,延伸到jmm的设计,以及这样的设计带来的影响,操作系统会通过实现一些一致性协议来解决这样的问题,java则通过上述一些方式来处理三大特性的问题,后续章节将介绍这些方式解决三大特性的原理。

.tb_button { padding: 1px; cursor: pointer; border-right: 1px solid rgba(139, 139, 139, 1); border-left: 1px solid rgba(255, 255, 255, 1); border-bottom: 1px solid rgba(255, 255, 255, 1) }
.tb_button.hover { borer: 2px outset #def; background-color: rgba(248, 248, 248, 1) !important }
.ws_toolbar { z-index: 100000 }
.ws_toolbar .ws_tb_btn { cursor: pointer; border: 1px solid rgba(85, 85, 85, 1); padding: 3px }
.tb_highlight { background-color: rgba(255, 255, 0, 1) }
.tb_hide { visibility: hidden }
.ws_toolbar img { padding: 2px; margin: 0 }
.tb_button { padding: 1px; cursor: pointer; border-right: 1px solid rgba(139, 139, 139, 1); border-left: 1px solid rgba(255, 255, 255, 1); border-bottom: 1px solid rgba(255, 255, 255, 1) }
.tb_button.hover { borer: 2px outset #def; background-color: rgba(248, 248, 248, 1) !important }
.ws_toolbar { z-index: 100000 }
.ws_toolbar .ws_tb_btn { cursor: pointer; border: 1px solid rgba(85, 85, 85, 1); padding: 3px }
.tb_highlight { background-color: rgba(255, 255, 0, 1) }
.tb_hide { visibility: hidden }
.ws_toolbar img { padding: 2px; margin: 0 }
.tb_button { padding: 1px; cursor: pointer; border-right: 1px solid rgba(139, 139, 139, 1); border-left: 1px solid rgba(255, 255, 255, 1); border-bottom: 1px solid rgba(255, 255, 255, 1) }
.tb_button.hover { borer: 2px outset #def; background-color: rgba(248, 248, 248, 1) !important }
.ws_toolbar { z-index: 100000 }
.ws_toolbar .ws_tb_btn { cursor: pointer; border: 1px solid rgba(85, 85, 85, 1); padding: 3px }
.tb_highlight { background-color: rgba(255, 255, 0, 1) }
.tb_hide { visibility: hidden }
.ws_toolbar img { padding: 2px; margin: 0 }

java内存模型(jmm)概念初探的更多相关文章

  1. Java内存模型JMM与可见性

    Java内存模型JMM与可见性 标签(空格分隔): java 1 何为JMM JMM:通俗地讲,就是描述Java中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量这 ...

  2. 多线程并发之java内存模型JMM

    多线程概念的引入是人类又一次有效压寨计算机的体现,而且这也是非常有必要的,因为一般运算过程中涉及到数据的读取,例如从磁盘.其他系统.数据库等,CPU的运算速度与数据读取速度有一个严重的不平衡,期间如果 ...

  3. Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)

    JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...

  4. 全面理解Java内存模型(JMM)及volatile关键字(转载)

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...

  5. 全面理解Java内存模型(JMM)及volatile关键字(转)

    原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...

  6. 对多线程java内存模型JMM

    多线程概念的引入体现了人类重新有效压力寨计算机.这是非常有必要的,由于所涉及的读数据的过程中的一般操作,如从磁盘.其他系统.数据库等,CPU计算速度和数据读取速度已经严重失衡.假设印刷过程中一个线程将 ...

  7. Java内存模型(JMM)详解

    在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型.它们的答案是一致的:能够让我们更好的 ...

  8. Java并发编程:Java内存模型JMM

    简介 Java内存模型英文叫做(Java Memory Model),简称为JMM.Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件和系统的内存访问差异,实现平台无关性. CPU和缓存一 ...

  9. 深入理解Java内存模型JMM

    本文转载自深入理解Java内存模型JMM JMM基础与happens-before 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执 ...

  10. 什么是Java内存模型(JMM)

    什么是java内存模型 缓存一致性问题 在现代计算机中,因为CPU的运算速度远大于内存的读写速度,因此为了不让CPU在计算的时候因为实时读取内存数据而影响运算速度,CPU会加入一层缓存,在运算之前缓存 ...

随机推荐

  1. Java新建一个子线程异步运行方法

    如何在运行主方法的同时异步运行另一个方法,我是用来更新缓存: 1. 工具类 public class ThreadPoolUtils { private static final Logger LOG ...

  2. 【LeetCode链表#12】链表相交

    链表相交 同:160.链表相交 力扣题目链接(opens new window) 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点.如果两个链表没有交点,返 ...

  3. HttpClient实现https调用

    在HttpClient 4.x版本中引入了大量的构造器设计模式 https请求建立详解 首先建立一个信任任何密钥的策略.代码很简单,不去考虑证书链和授权类型,均认为是受信任的: class AnyTr ...

  4. 【Azure 应用服务】使用Docker Compose创建App Service遇见"Linux Version is too long. It cannot be more than 4000 characters"错误

    问题描述 使用Docker Compose方式合并多个镜像(Images)文件,然后部署到App Service中,结果失败.报错 Linux Version 太长,不能超过4000个字符. 错误消息 ...

  5. 图像识别算法--VGG16

    前言:人类科技就是不断烧开水(发电).丢石头(航天等).深度学习就是一个不断解方程的过程(参数量格外大的方程) 本文内容: 1.介绍VGG16基本原理 2.VGG16 pytorch复现 图像识别算法 ...

  6. Program type already present: com.xxx

    该错误是由于工程中存在着相同的类导致(包名与类名都相同),有可能是不同的依赖中有着相同的类,全局搜索该类便可得知

  7. window.open代理劫持

    window.open = new Proxy(window.open, { apply(target, ctx, args) { if (hasAuth(args[0])) { return tar ...

  8. Vue.prototype.$app = this vscode ctrl 点击 不跳转

    Vue.prototype.$app = this vscode ctrl 点击 不跳转 解决思路 src/types/vue.d.ts 里面写,具体还没解决,找到一篇 在js里面的 我这种直接将当前 ...

  9. archlinux 使用ventoyU盘启动器(ISO)

    ventoy详细介绍https://www.ventoy.net/cn/doc_start.html Linux系统安装 Ventoy -- 命令行界面 下载安装包,例如 ventoy-1.0.00- ...

  10. B站Aimls的JavaFx教程目录合集

    B站里有时候不太好去找资源,用JS爬了下,整出标题和链接,方便后续查询某个知识点的使用! JavaFX视频教程第1课,hello world JavaFX视频教程第2课,application的启动方 ...