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

整体方向

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

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

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

JVM 内存结构

在这里插入图片描述

Java 对象模型

在这里插入图片描述
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 却看不到,引出可见性问题

在这里插入图片描述

可见性

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

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

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

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

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

主内存和本地内存

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

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

在这里插入图片描述

  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原则
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值