JVM内存结构 VS Java内存模型 VS Java对象模型

整体方向

JVM 内存结构,和 Java 虚拟机的运行时区域有关。

Java 内存模型,和 Java 的并发编程有关。

Java 对象模型,和 Java 对象在虚拟机中的表现形式有关。

JVM 内存结构

JVM内存结构 VS Java内存模型 VS Java对象模型_第1张图片

Java 对象模型

JVM内存结构 VS Java内存模型 VS Java对象模型_第2张图片
Java 对象自身的存储模型

JVM 会给这个类创建一个 instanceKlass,保存在方法区,用来在JVM层表示该 Java 类。

当我们在 Java 代码中,使用 new 创建一个对象的时候,JVM 会创建一个 instanceOopDesc 对象,这个对象中包含了对象头以及实例数据。

Java 内存模型

为什么需要 JMM

  • C 语言不存在内存模型的概念
  • 依赖处理器,不同处理器结果不一样
  • 无法保证并发安全
  • 需要一个标准,让多线程运行的结果可预期

JMM 是规范

  • Java Memory Model
  • 是一组规范,需要各个 JVM 的实现来遵守 JMM 规范,以便于开发者可以利用这些规范,更方便地开发多线程程序。
  • 如果没有这样的一个 JMM 内存模型来规范,那么很可能经过了不同 JVM 的不同规则的重排序之后,导致不同的虚拟机上运行的结果不一样那是很大的问题。

JMM 是工具类和关键字的原理
volatile、synchronized、 Lock 等的原理都是 JMM 如果没有 JMM,那就需要我们自己指定什么时候用内存栅栏等,那相当麻烦的,幸好有了JMM ,让我们只需要用同步工具和关键字就可以开发并发程序。

最重要的 3 点内容:重排序可见性原子性

重排序

重排序的好处:提高处理速度

重排序的 3 种情况:编译器优化、CPU指令重排、内存的“重排序”

编译器优化:包括JVM , JIT编译器等

CPU指令重排:就算编译器不发生重排,CPU也可能对指令进行重排

内存的“重排序”:线程 A 的修改线程 B 却看不到,引出可见性问题

JVM内存结构 VS Java内存模型 VS Java对象模型_第3张图片

可见性

CPU 有多级缓存,导致读的数据过期

  • 高速缓存的容量比主内存小,但是速度仅次于寄存器,所以在CPU和主内存之间就多了Cache 层

  • 线程间的对于共享变量的可见性问题不是直接由多核引起的,而是由多缓存弓|起的。

  • 如果所有个核心都只用一个缓存,那么也就不存在内存可见性问题了。

  • 每个核心都会将自己需要的数据读到独占缓存中,数据修改后也是写入到缓存中,然后等待刷入到主存中。所以会导致有些核心读取的值是一个过期的值。

主内存和本地内存

Java 作为高级语言, 屏蔽了这些底层细节,用JMM定义了一套读写内存数据的规范,虽然我们不再需要关心一级缓存和二级缓存的问题,但是,JMM 抽象了主内存和本地内存的概念。

这里说的本地内存并不是真的是一块给每个线程分配的内存,而是JMM的一个抽象,是对于寄存器、一级缓存、 二级缓存等的抽象。

JVM内存结构 VS Java内存模型 VS Java对象模型_第4张图片

  1. 所有的变量都存储在主内存中,同时每个线程也有自己独立的工作内存,工作内存中的变量内容是主内存中的拷贝
  2. 线程不能直接读写主内存中的变量,而是只能操作自己工作内存中的变量然后再同步到主内存中
  3. 主内存是多个线程共享的,但线程间不共享工作内存,如果线程间需要通信,必须借助主内存中转来完成

Happens-Before 原则

Happens-Before 规则是用来解决可见性问题的:在时间上,动作 A 发生在动作 B 之前,B 保证能看见 A,这就是 Happens-Before

  1. 单线程规则
  2. 锁操作(synchronized和Lock)
  3. volatile变量
  4. 线程启动
  5. 线程join
  6. 传递性
  7. 中断
  8. 构造方法
  9. 工具类的Happens-Before原则

你可能感兴趣的:(多线程,多线程)