思考:Java内存模型和硬件内存模型

前言

前一阵在看volatile的原理,看到内存屏障和缓存一致性,发现再往底层挖就挖到了硬件和Java内存模型。这一块是自己似懂非懂的知识区,我一般称之为知识混沌区。因此整理这一篇文章。

什么是内存模型(Memory Model)呢?它是系统和程序员之间的规范,它规定了存储器访问的行为,并影响到了性能。并且,Memory Model有多层,处理器规定、编译器规定、高级语。对于高级语言来说,如Java内存模型, 它通常需要支持跨平台,也就是说它会基于各种不同的内存模型,但是又要提供给程序员一个统一的内存模型,可以理解为一个适配器的角色。

这篇文字主要包含了三部分:

  1. 硬件内存模型

  2. Java内存模型和运行时数据区

  3. 三者的关系

硬件内存模型

下图是2012 Sandy Bridge(一种Intel处理器)核心设计。图中有socket1和socket2,可以理解为了这台电脑中有两个插cpu的槽,每个槽中有一个多核(C1,C2...Cn)的cpu。对于CPU的内存模型可以大致按照如下进行分解:

寄存器

编译器会将本地变量和函数参数分配到这些寄存器上

内存排序缓冲(Memory Ordering Buffers)

这些缓冲用于记录等待缓存子系统时正在执行的操作

L1 缓存

空间最小,访问速度最快

L2缓存

要作用是作为L1和L3之间的高效内存访问队列。L2缓存同时包含数据和指令

L3缓存

在同插槽的所有核心都共享L3缓存。

主内存

在缓存完全没命中的情况下

简化之后如下图所示,计算机在高速的 CPU 和相对低速的存储设备(内存,RAM)之间使用高速缓存,作为内存和处理器之间的缓冲。将运算需要使用到的数据复制到缓存中,让运算能快速运行,当运算结束后再从缓存同步回内存之中。

在多处理器的系统中(或者单处理器多核的系统),每个处理器内核都有自己的高速缓存,它们有共享同一主内存(Main Memory---RAM)。

Java内存模型和运行时数据区

说完系统的内存模型,然后开始说一下Java的内存模型(Java Memory Model,简称 JMM)。

    

Java语言一大特性就是跨平台型。其背后的实现便是在Java 虚拟机规范中定义的Java 内存模型(Java Memory Model,简称 JMM)。

虚拟机通过内存模型,定义了将变量存储到内存和从内存中取出变量的底层细节(字节码指令转换是另一方面),屏蔽掉各种硬件和操作系统的内存访问差异,实现让 Java 程序在各种平台下都能达到一致的内存访问效果,不必因为不同平台上的物理机的内存模型的差异,对各平台定制化开发程序。

上面提到了两个重要的概念--内存和变量。

先说内存,Java内存模型中的内存分为两类:主内存(Main Memory)和工作内存(Working Memory,又称本地内存)。其详情如下:

主内存可以类比成物理硬件的主内存,但此处仅是虚拟机内存的部分。工作内存可以类比成处理器高速缓存

主内存是所有的线程共享,每个线程都有自己的工作内存,属于线程私有。

一个线程不能访问另一个线程的工作内存,线程之间需要通过主内存来实现线程间的通信;

线程的工作内存中保存了该线程使用到的变量的主内存副本拷贝,线程对变量的所有的操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存的变量;

如果想理解上面提到的变量(Variables)的提取和存储。那就需要继续看一下JVM另一个重要的知识点--运行时数据区。如下图所示,不同jdk版本的运行时数据区划分有所差异。但主要分为了五部分:方法区(8开始使用元数据),堆,栈,程序计数器,本地方法栈。细节就不展开讲。

内存模型中管理的变量(Variables)则主要指是堆中的数据,它包括了实例字段、静态字段和构成数值对象的元素,如数组等。但不包括Java方法中局部变量与方法参数,如果局部变量是一个 reference 类型,它引用的对象在 Java 堆中可被各个线程共享,但是 reference 本身在 Java 栈的局部变量表中。

总结一下:Java 运行时数据区和内存模型是不一样的东西,更确切的说应该是不是同一层次的东西。

  1. 内存模型:是定义了线程和主内存之间的抽象关系,更多的是定义规则

  2. 运行时数据区域:是指 JVM 运行时将数据分区域存储,强调对内存空间的划分。

硬件内存模型和Java内存模型关系

Java内存模型中的主内存和工作内存的区别在于线程调度和共享的区别,而不是物理层面的区别。因此硬是将Java内存模型和硬件内存模型进行映射没有意义。如果真的有关系,只能说工作内存更多的是CPU寄存器和缓存。当然,工作内存由于上下文切换等原因,也可能会写回RAM(可以理解为物理内存,严谨来说是物理虚拟内存)。

对于运行时数据区而言,有些是随着虚拟机启动而创建,虚拟机关闭而销毁。还有一部分是随着线程生命周期创建销毁的。

线程间共享的方法区和堆,是说它们会随着虚拟机启动而创建,随着虚拟机退出而销毁。而栈和程序计数器会随着线程开始和结束而创建和销毁。

正如下图所示,方法区和堆在RAM中,也可以在缓存中,这也是JVM创建时进行管理的内存空间。

以堆为例,由于对象实例的创建在JVM中非常频繁,一方面保证并发环境下从堆区中划分内存空间的线程安全,另一方面提升内存分配的吞吐量。对Eden区域继续进行划分,JVM为每个线程分配一个私有缓存区域--本地线程分配缓冲((Thread Local Allocation Buffer,TLAB)。而这个缓冲则缓存中,而不是RAM中

如前所述,Java内存模型和硬件内存架构是不同的。 线程栈和堆的一部分有时可能存在于CPU高速缓存和内部CPU寄存器中。 

参考资料:

https://jenkov.com/tutorials/java-concurrency/java-memory-model.html

指令重排序 - 简书

https://www.cnblogs.com/czwbig/p/11127124.html

https://zhuanlan.zhihu.com/p/51613784

Java 运行时数据区和内存模型(JMM)_jmm 和运行时数据区 的关系看-CSDN博客

简单介绍一下什么是“工作内存”和“主内存”(JMM中的概念)_工作内存和主内存-CSDN博客

JVM运行时数据区------堆_数据区和堆-CSDN博客

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

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

相关文章

CentOS6用文件配置IP模板

CentOS6用文件配置IP模板 到 CentOS6.9 , 默认还不能用 systemctl , 能用 service chkconfig sshd on 对应 systemctl enable sshd 启用,开机启动该服务 ### chkconfig sshd on 对应 systemctl enable sshd 启用,开机启动该服务 sudo chkconfig sshd onservice sshd start …

未羽研发测试管理平台

突然有一些觉悟,程序猿不能只会吭哧吭哧的低头做事,应该学会怎么去展示自己,怎么去宣传自己,怎么把自己想做的事表述清楚。 于是,这两天一直在整理自己的作品,也为接下来的找工作多做点准备。接下来…

LT7911UX 国产原装 一拖三 edp 转LVDS 可旋转 可缩放

2.一般说明 该LT7911UX是一种高性能Type-C/DP1.4a到MIPI或LVDS芯片的VR/显示应用。HDCP RX作为HDCP转发器的上游,可以与其他芯片的HDCP TX配合实现转发器功能。 对于DP1.4a输入,LT7911UX可配置为1/2/4通道。自适应均衡使其适用于长电缆应用,最…

Junior.Crypt.2024 CTF Web方向 题解WirteUp 全

Buy a cat 题目描述:Buy a cat 开题 第一思路是抓包改包 Very Secure App 题目描述:All secrets become clear 开题 乱输一个密码就登陆成功了(不是弱口令) 但是回显Your role is: user 但是有jwt!!&a…

深入理解基本数据结构:链表详解

引言 在计算机科学中,数据结构是存储、组织和管理数据的方式。链表是一种重要的线性数据结构,广泛应用于各种编程场景。在这篇博客中,我们将详细探讨链表的定义、特点、操作及其在不同编程语言中的实现。 什么是链表? 链表是一种…

Mobile ALOHA前传之VINN, Diffusion Policy和ACT对比

VINNDiffusion PolicyACT核心思想1.从离线数据中自监督学习获得一个视觉编码器;2.基于视觉编码器,从采集的示例操作数据中检索与当前观测图像最相似的N张图像以及对应的动作;3.基于图像编码器的距离对各个动作进行加权平均,获得最…

Open3D loss函数优化的ICP配准算法(精配准)

目录 一、概述 1.1ICP的基本步骤 1.2损失函数的设计 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2配准后点云 3.3计算数据 一、概述 ICP(Iterative Closest Point)配准算法是一种用于对齐两个点云的经典算法。其目标是通过迭代优化…

Istio实战教程:Service Mesh部署与流量管理

引言 Istio是一个开源的服务网格,它提供了一种统一的方法来连接、保护、控制和观察服务。本教程将指导你从零开始部署Istio,并展示如何使用Istio进行基本的流量管理。 环境准备 Kubernetes集群:Istio运行在Kubernetes之上,确保…

W25Q64 Flash存储器与STM32:硬件与软件的完美结合案例

摘要 在嵌入式系统中,数据存储是关键组成部分之一。W25Q64 Flash存储器因其高容量、低功耗和高可靠性,成为STM32微控制器项目中优选的存储解决方案。本文将展示W25Q64与STM32微控制器集成的案例,包括硬件设计、SPI通信协议实现和软件编程策略…

记录在Windows上安装Docker

在Windows上安装Docker时,可以选择使用不同的后端。 其中两个常见的选择是:WSL 2(Windows Subsystem for Linux 2)和 Hyper-V 后端。此外,还可以选择使用Windows容器。 三者的区别了解即可,推荐用WSL 2&…

我们公司落地大模型的路径、方法和坑

我们公司落地大模型的路径、方法和坑 李木子 AI大模型实验室 2024年07月02日 18:35 北京 最近一年,LLM(大型语言模型)已经成熟到可以投入实际应用中了。预计到 2025 年,AI 领域的投资会飙升到 2000 亿美元。现在,不只…

Thinking--在应用中添加动态水印,且不可删除

Thinking系列,旨在利用10分钟的时间传达一种可落地的编程思想。 水印是一种用于保护版权和识别内容的技术,通常用于图像、视频或文档中。它可以是文本、图像或两者的组合,通常半透明或以某种方式嵌入到内容中,使其不易被移除或篡改…

【Linux】多线程_2

文章目录 九、多线程2. 线程的控制 未完待续 九、多线程 2. 线程的控制 主线程退出 等同于 进程退出 等同于 所有线程都退出。为了避免主线程退出,但是新线程并没有执行完自己的任务的问题,主线程同样要跟进程一样等待新线程返回。 pthread_join 函数…

【代码随想录_Day28】62. 不同路径 63. 不同路径 II

Day28 OK,今日份的打卡!第二十八天 以下是今日份的总结不同路径不同路径 II 以下是今日份的总结 62 不同路径 63 不同路径 II 今天的题目难度不低,尽量还是写一些简洁代码 ^ _ ^ 不同路径 思路: 1.确定dp数组(dp…

算法学习笔记(8.2)-动态规划入门进阶

目录 问题判断: 问题求解步骤: 图例: 解析: 方法一:暴力搜索 实现代码如下所示: 解析: 方法二:记忆化搜索 代码示例: 解析: 方法三:动态规划 空间…

每日复盘-20240709

今日关注: 20240709 六日涨幅最大: ------1--------300391--------- 长药控股 五日涨幅最大: ------1--------300391--------- 长药控股 四日涨幅最大: ------1--------603155--------- 新亚强 三日涨幅最大: ------1--------301300--------- 远翔新材 二日涨幅最大: ------1-…

基于antdesign封装一个react的上传组件

项目中遇到了一个上传的需求,看了一下已有的代码很粗糙,而且是直接引用andt的组件,体验不太好,自己使用FormData对象封装了一个上传组件,仅供参考。 代码如下: /*** FileUploadModal* description - 文件选…

Qt入门(二):Qt的基本组件

目录 Designer程序面板 1、布局Layout 打破布局 贴合窗口 2、QWidget的属性 3、Qlabel标签 显示图片 4、QAbstractButton 按钮类 按钮组 5、QLineEdit 单行文本输入框 6、ComboBox 组合框 7、若干与数字相关的组件 Designer程序面板 Qt包含了一个Designer程序 &…

Qt编程技巧总结篇(3)-信号-槽-多线程(二)

文章目录 Qt编程技巧总结篇(3)-信号-槽-多线程(二)主进程与子线程线程同步实例与应用 小结 Qt编程技巧总结篇(3)-信号-槽-多线程(二) 多线程学习,使用QMutex,…

RTK_ROS_导航(3):点云的压缩,PointCloud转scan

目录 1. 源码的安装2. 修改订阅的话题3. 可视化1. 源码的安装 安装过程如下 mkdir -p point_to_scan_ws/src cd point_to_scan_ws/src git clone https://github.com/BluewhaleRobot/pointcloud_to_laserscan.git cd .. catkin_make source devel/setup.bash2. 修改订阅的话题 …