美文网首页
8.jmm内存模型

8.jmm内存模型

作者: 段段小胖砸 | 来源:发表于2021-08-27 16:20 被阅读0次

jmm:java内存模型,它的提出是为了解决多线程情况下的一些问题

1:内存可见性

在一个CPU的4核下,L1、L2、L3三级缓存与主内存的布局。
每个核上面有L1、L2缓存,L3缓存为所有核共用,通过L3向主内存(内存条)同步,L1,L2,L3都是在cpu中,L1.L2,通过L3实现同步,这种情况下,内存是可见的。


image.png

因为存在CPU缓存一致性协议,例如MESI,多个CPU核心之间缓存不会出现不同步的问题,不会有
“内存可见性”问题。
缓存一致性协议对性能有很大损耗,为了解决这个问题,又进行了各种优化。例如,在计算单元和
L1之间加了Store Buffer、Load Buffer


image.png

L1、L2、L3和主内存之间是同步的,有缓存一致性协议的保证,但是Store Buffer、Load Buffer和L1之间却是异步的。向内存中写入一个变量,这个变量会保存在Store Buffer里面,稍后才异步地写入L1中,同时同步写入主内存中。所以buffer和L1、L2、L3、主内存之间不是同步的,就存在内存可见性的问题。

对应到java中,就是jvm抽象内存模型,如图

image.png

2.重排序和内存可见性的关系

重排序类型:
1. 编译器重排序。
对于没有先后依赖关系的语句,编译器可以重新调整语句的执行顺序。
2. CPU指令重排序。
在指令级别,让没有依赖关系的多条指令并行。
3. CPU内存重排序。
CPU有自己的缓存,指令的执行顺序和写入主内存的顺序不完全一致。

其中第三类是java中的内存可见性问题的主因。*

例如:

线程1:
X=1
a=Y
线程2:
Y=1
b=X

线程1和线程2的执行先后顺序是不确定的,可能顺序执行,也可能交叉执行,最终正确的结果可能是:

  1. a=0,b=1
  2. a=1,b=0
  3. a=1,b=1

但实际可能是a=0,b=0。两个线程的指令都没有重排序,执行顺序就是代码的顺序,但仍然可能出现a=0,b=0。原因是线程1先执行X=1,后执行a=Y,但此时X=1还在自己的Store Buffer里面,没有及时写入主内存中。所以,线程2看到的X还是0。线程2的道理与此相同。指令没有重排序,是写入内存的操作被延迟了,也就是内存被重排序了,这就造成内存可见性问题

内存屏障

为了禁止编译器重排序和 CPU 重排序,在编译器和 CPU 层面都有对应的指令,也就是内存屏障(Memory Barrier)。这也正是JMM和happen-before规则的底层实现原理。

  • 编译器的内存屏障,只是为了告诉编译器不要对指令进行重排序。当编译完成之后,这种内存屏障就消失了,CPU并不会感知到编译器中内存屏障的存在。
  • CPU的内存屏障是CPU提供的指令,可以由开发者显示调用。
  • 内存屏障是很底层的概念,对于 Java 开发者来说,一般用 volatile 关键字就足够了。

happen-before

使用happen-before描述两个操作之间的内存可见性。

在多线程中,一方面,要让编译器和CPU可以灵活地重排序;
另一方面,要对开发者做一些承诺,明确告知开发者不需要感知什么样的重排序,需要感知什么样的重排序。然后,根据需要决定这种重排序对程序是否有影响。如果有影响,就需要开发者显示地通过volatile、synchronized等线程同步机制来禁止重排序。

如果A happen-before B,意味着A的执行结果必须对B可见,也就是保证跨线程的内存可见性。

JMM对编译器和CPU 来说,volatile 变量不能重排序;非 volatile 变量可以任意重排序。

happen-before的传递性:
即若A happen-before B,B happen-before C,则A happen-before C。

如果一个变量不是volatile变量,当一个线程读取、一个线程写入时可能有问题。那岂不是说,在多
线程程序中,我们要么加锁,要么必须把所有变量都声明为volatile变量?这显然不可能,而这就得归功于happen-before的传递性。只需要在操作中给其中关键操作的变量声明即可。

相关文章

  • 8.jmm内存模型

    jmm:java内存模型,它的提出是为了解决多线程情况下的一些问题 1:内存可见性 在一个CPU的4核下,L1、L...

  • Flink JobManager | TaskManager内存

    Flink内存模型分析 JobManager内存模型 TaskManager内存模型 内存模型分析 Flink使用...

  • 图解jvm--(四)内存模型

    内存模型 java 内存模型 很多人将【java 内存结构】与【java 内存模型】傻傻分不清,【java 内存模...

  • JVM内存模型(jvm 入门篇)

    概述 jvm 入门篇,想要学习jvm,必须先得了解JVM内存模型,JVM内存模型,JVM内存模型,JVM内存模型,...

  • java内存模型

    1.内存模型(JMM) 1.1什么是Java内存模型? Java内存模型将内存分为主内存和工作内存两大部分;主内存...

  • [Java多线程编程之八] Java内存模型

    一、Java内存模型 == JVM内存模型?   很多人都会认为Java内存模型就是JVM内存模型,但实际上是错的...

  • 深度解析Java多线程的内存模型

    内部java内存模型 硬件层面的内存模型 Java内存模型和硬件内存模型的联系 共享对象的可见性 资源竞速 Jav...

  • java虚拟机-内存模型与线程

    一、java内存模型 java定义的内存模型是类似物理计算机的三级缓存模型 1.主内存与工作内存 java内存模型...

  • CPU内存模型 和 JAVA内存模型 讲解

    CPU 内存模型 在讲解 JAVA 内存模型之前,先了解 CPU 内存模型,因为JAVA内存模型跟它是十分相似的。...

  • Java基础之内存模型

    Java基础之内存模型 目录 Java内存模型简单介绍 JVM介绍 存储方式 并发原因 Java内存模型与系统内存...

网友评论

      本文标题:8.jmm内存模型

      本文链接:https://www.haomeiwen.com/subject/qoymiltx.html