【面试】说说什么是 Java 内存模型(JMM)?

news2024/11/19 5:55:32

文章目录

  • 一、 为什么要有内存模型?
    • 1.1. 硬件内存架构
    • 1.2. 缓存一致性问题
    • 1.3. 处理器优化和指令重排序
  • 二、并发编程的问题
  • 三、Java 内存模型
    • 3.1. Java 运行时内存区域与硬件内存的关系
    • 3.2. Java 线程与主内存的关系
    • 3.3. 线程间通信
  • 四、总结

一、 为什么要有内存模型?

要想回答这个问题,我们需要先弄懂传统计算机硬件内存架构。好了,我要开始画图了。

1.1. 硬件内存架构

在这里插入图片描述

  • CPU

去过机房的同学都知道,一般在大型服务器上会配置多个CPU,每个CPU还会有多个核,这就意味着多个CPU或者多个核可以同时(并发)工作。如果使用Java 起了一个多线程的任务,很有可能每个 CPU 都会跑一个线程,那么你的任务在某一刻就是真正并发执行了。

  • CPU Register

CPU Register也就是 CPU 寄存器。CPU 寄存器是 CPU 内部集成的,在寄存器上执行操作的效率要比在主存上高出几个数量级。

  • CPU Cache Memory

CPU Cache Memory也就是 CPU 高速缓存,相对于寄存器来说,通常也可以成为 L2 二级缓存。相对于硬盘读取速度来说内存读取的效率非常高,但是与 CPU 还是相差数量级,所以在 CPU 和主存间引入了多级缓存,目的是为了做一下缓冲。

  • Main Memory

Main Memory 就是主存,主存比 L1、L2 缓存要大很多。

注意:部分高端机器还有 L3 三级缓存。

1.2. 缓存一致性问题

由于主存与 CPU 处理器的运算能力之间有数量级的差距,所以在传统计算机内存架构中会引入高速缓存来作为主存和处理器之间的缓冲,CPU 将常用的数据放在高速缓存中,运算结束后 CPU 再讲运算结果同步到主存中。

使用高速缓存解决了 CPU 和主存速率不匹配的问题,但同时又引入另外一个新问题:缓存一致性问题。
在这里插入图片描述

在多CPU的系统中(或者单CPU多核的系统),每个CPU内核都有自己的高速缓存,它们共享同一主内存(Main Memory)。当多个CPU的运算任务都涉及同一块主内存区域时,CPU 会将数据读取到缓存中进行运算,这可能会导致各自的缓存数据不一致。

因此需要每个 CPU 访问缓存时遵循一定的协议,在读写数据时根据协议进行操作,共同来维护缓存的一致性。这类协议有 MSI、MESI、MOSI、和 Dragon Protocol 等。

1.3. 处理器优化和指令重排序

为了提升性能在 CPU 和主内存之间增加了高速缓存,但在多线程并发场景可能会遇到缓存一致性问题。那还有没有办法进一步提升 CPU 的执行效率呢?答案是:处理器优化。

为了使处理器内部的运算单元能够最大化被充分利用,处理器会对输入代码进行乱序执行处理,这就是处理器优化。

除了处理器会对代码进行优化处理,很多现代编程语言的编译器也会做类似的优化,比如像 Java 的即时编译器(JIT)会做指令重排序。

在这里插入图片描述

处理器优化其实也是重排序的一种类型,这里总结一下,重排序可以分为三种类型:

  • 编译器优化的重排序。编译器在不改变单线程程序语义放入前提下,可以重新安排语句的执行顺序。
  • 指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
  • 内存系统的重排序。由于处理器使用缓存和读写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

二、并发编程的问题

上面讲了一堆硬件相关的东西,有些同学可能会有点懵,绕了这么大圈,这些东西跟 Java 内存模型有啥关系吗?不要急咱们慢慢往下看。

熟悉 Java 并发的同学肯定对这三个问题很熟悉:『可见性问题』、『原子性问题』、『有序性问题』。如果从更深层次看这三个问题,其实就是上面讲的『缓存一致性』、『处理器优化』、『指令重排序』造成的。

在这里插入图片描述

缓存一致性问题其实就是可见性问题,处理器优化可能会造成原子性问题,指令重排序会造成有序性问题,你看是不是都联系上了。

出了问题总是要解决的,那有什么办法呢?首先想到简单粗暴的办法,干掉缓存让 CPU 直接与主内存交互就解决了可见性问题,禁止处理器优化和指令重排序就解决了原子性和有序性问题,但这样一夜回到解放前了,显然不可取。

所以技术前辈们想到了在物理机器上定义出一套内存模型, 规范内存的读写操作。内存模型解决并发问题主要采用两种方式:限制处理器优化和使用内存屏障。

三、Java 内存模型

同一套内存模型规范,不同语言在实现上可能会有些差别。接下来着重讲一下 Java 内存模型实现原理。

3.1. Java 运行时内存区域与硬件内存的关系

了解过 JVM 的同学都知道,JVM 运行时内存区域是分片的,分为栈、堆等,其实这些都是 JVM 定义的逻辑概念。在传统的硬件内存架构中是没有栈和堆这种概念。
在这里插入图片描述

从图中可以看出栈和堆既存在于高速缓存中又存在于主内存中,所以两者并没有很直接的关系。

3.2. Java 线程与主内存的关系

Java 内存模型是一种规范,定义了很多东西:

所有的变量都存储在主内存(Main Memory)中。
每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的拷贝副本。
线程对变量的所有操作都必须在本地内存中进行,而不能直接读写主内存。
不同的线程之间无法直接访问对方本地内存中的变量。

3.3. 线程间通信

如果两个线程都对一个共享变量进行操作,共享变量初始值为 1,每个线程都变量进行加 1,预期共享变量的值为 3。在 JMM 规范下会有一系列的操作。

为了更好的控制主内存和本地内存的交互,Java 内存模型定义了八种操作来实现:

  • lock:锁定。作用于主内存的变量,把一个变量标识为一条线程独占状态。
  • unlock:解锁。作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
  • read:读取。作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用
  • load:载入。作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
  • use:使用。作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
  • assign:赋值。作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
  • store:存储。作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。
  • write:写入。作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。

注意:工作内存也就是本地内存的意思。

四、总结

由于CPU 和主内存间存在数量级的速率差,想到了引入了多级高速缓存的传统硬件内存架构来解决,多级高速缓存作为 CPU 和主内间的缓冲提升了整体性能。解决了速率差的问题,却又带来了缓存一致性问题。

数据同时存在于高速缓存和主内存中,如果不加以规范势必造成灾难,因此在传统机器上又抽象出了内存模型。

Java 语言在遵循内存模型的基础上推出了 JMM 规范,目的是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题。

为了更精准控制工作内存和主内存间的交互,JMM 还定义了八种操作:lock, unlock, read, load,use,assign, store, write。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/502705.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java阶段二Day16

Java阶段二Day16 文章目录 Java阶段二Day16SSMSpringBoot简述核心特性创建SpringBoot工程创建工程失败排查 MyBatis框架-注解管理概述MyBatis环境初始化整合MyBatisPojo对象设计Dao接口设计 SSM Spring:Spring是一个轻量级的容器和框架,为开发者提供了一…

沃通“SSL证书+代码签名证书”,防范高仿“钓鱼网站+钓鱼软件”攻击

近日,360发布威胁预警,因监测发现多起利用钓鱼网站对特定用户进行攻击的安全事件,呼吁警惕“高仿”软件安装程序暗藏钓鱼木马。“钓鱼网站钓鱼软件”是非常典型的钓鱼攻击组合,而沃通“SSL证书代码签名证书”能够帮助企业建立安全…

一文带你直观感受,BPM管理系统如何在低代码平台实现搭建

BPM系统(英文全称:Business Process Management,翻译后简称BPM)即业务流程管理系统,是指对端到端业务流程进行建模、分析和优化,用以实现战略业务目标,其特点是注重流程驱动为核心,实…

通过修改根证书绕过rustls的证书固定机制,抓包解密ssl流量

例子,cloudflare的warp-svc.exe。抓包获取密钥。 用proxifier尝试了一下强行代理,无效,因为proxifier是通过Hook Socket函数方式实现的,但这个程序可能没有用Socket函数进行通信。 之后发现通过nekoray基于gvisor的VPN白名单模式全…

《计算机网络——自顶向下方法》精炼——3.1-3.4.1

“生命在于运动,学习在于不断尝试。”——亚里士多德 文章目录 运输层概述与服务运输层功能运输层概述IP协议UDP和TCP协议 多路复用与多路分解UDPUDP相较于TCP的优点UDP报文段结构检验和可靠数据传输构造可靠数据传输协议 运输层概述与服务 运输层为应用层提供了逻…

2022年宜昌市网络搭建与应用竞赛样题(二)

网络搭建与应用竞赛样题(二) 技能要求 (总分1000分) 竞赛说明 一、竞赛内容分布 “网络搭建与应用”竞赛共分三个部分,其中: 第一部分:网络搭建及安全部署项目(500分&#xff0…

传统工厂布局数字化的核心因素——智能工厂

近年来很多鼓励企业数字化转型的政策陆续出台,在一定程度上帮助企业减轻数字化转型的成本压力。但是企业数字化转型依然面临着诸多的问题与挑战。主要还是因为大部分企业,特别是制造型企业,数字化进程还在探索阶段,资金、人才、技…

接口自动化测试详解——持续集成流程中不可或缺的一环

B站首推!2023最详细自动化测试合集,小白皆可掌握,让测试变得简单、快捷、可靠https://www.bilibili.com/video/BV1ua4y1V7Db 目录 接口自动化测试 Jenkins持续集成 总结 摘要: 在软件开发中,自动化测试已经成为了…

过滤器、拦截器、aop -> ‘三兄弟‘

目录 一、熟悉 三兄弟的区别 过滤器和拦截器的区别 使用场景 二、使用 filter Interceptor aop 一、熟悉 三个词都很熟悉,在某些课程或者博客中总被提到,但平时基本不怎么写; 三者在家族中的关系可以看下下边这张图,可以很…

52.现有移动端开源框架及其特点—PocketFlow-2

PocketFlow 性能 通过引入超参数优化组件,不仅避免了高门槛、繁琐的人工调参工作,同时也使得 PocketFlow 在各个压缩算法上全面超过了人工调参的效果。以图像分类任务为例,在 CIFAR-10 和 ImageNet 等数据集上,PocketFlow 对 ResNet 和 MobileNet 等多种 CNN 网络结构进行…

LT8471IFE#PBF-ASEMI代理亚德诺LT8471IFE#PBF原厂芯片

编辑-Z LT8471IFE#PBF参数描述: 型号:LT8471IFE#PBF 输入电压:2.6-50V 静态电流:2.2 mA 停机时的静态电流:0.01μA 正反馈电压:789 mV 反馈引脚偏置电流:30 nA 开关频率范围&#xff1a…

产品经理该怎么催进度?

这算是一个项目管理相关的问题,很多公司会把产品经理与项目经理的工作职能划分并没有这么清晰,而且项目是否能够按时上线,在整个项目推进过程中也是至关重要的。如果是公司的自研产品,项目没办法定期交付,挨老板一顿骂…

Barotrauma潜渊症私人服务器架设教程

准备工具: 服务器一台(Ubuntu系统) 家用电脑一台(有网就行) 准备阶段 通过SSH登入服务器。 服务端需要下载三个软件。 窗口管理工具 Screen 。用于将服务器挂在后台中运行。 SteamCMD 。用于下载潜渊症服务器。 …

【YOLO 系列】YOLO v4-v5先验知识

文章目录 输入端Mosaic数据增强Self-Adversarial TrainingCmBN 主干网络Mish激活函数DropBlock 正则化CSPNetFocus结构 NeckPANet 输出目标损失函数IoU LossGIoU LossDIoU LossCIoU Loss总结 DIOU_nms 参考 YOLO v4和v5版本在v3版本的基础上,组合了多种先进算法提升…

OLAP分析型数据库clickhouse的选型、安装与试用

一、背景: 目前,在做项目时,遇到使用oracle数据库进行大表查询分析时,查询比较慢,而且随着表数据逐渐积累,数据量过亿(按月估计)。架构师针对几个关键要点(非实时数据、核心场景查询分析、对事务要求低、数…

谷粒商城二十四springCloud之Sleuth+Zipkin 服务链路追踪

为什么用 微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元。由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去定位。 主要体现在,一个请求可能需要调…

进程同步及经典问题

目录 1、基本概念 1.1两种形式的制约关系 1.2临界资源 1.3临界区 1.4同步机制应遵循的规则 2、硬件同步机制 3、信号量机制(重要) 3.1整型信号量 3.2记录型信号量 3.3AND型信号量 3.4信号量集 4、信号量的应用 4.1利用信号量实现进程互斥 4.2利用信号量实现前趋关系 …

【Spring】初识MyBatis (一)

MyBatis概述 MyBatis是一个支持普通SQL查询、存储过程以及高级映射的持久层框架,它消除了几乎所有的JDBC代码和参数的手动设置以及对结果集的检索,并使用简单的XML或注解进行配置和原始映射,用以将接口和Java的POJO(Plain Old Ja…

Qt libqrencode二维码——QtWidgets

前言 之前写过二维码的程序,但是在U盘上,没带,又重新找的网上资料写的。 网上二维码的生成,大多用到是第三方库libqrencode,这也一样: 效果图 本来是个动图的,都被和谐了,所以换成截图&…

2023年必学的一款测试工具,10 分钟上手

近两年有一款 UI 测试工具非常火爆,名字叫 cypress, 官方号称超越 selenium, 是面向下一代的测试工具。 那 cypress 到底要不要学呢?学起来容易吗?我们一起来看一下。 资料传送门:《软件测试全套基础/进阶/转行资料》 安装 cy…