关于Java内存模型的理解

news/2024/4/27 7:57:45/文章来源:https://blog.csdn.net/BAStriver/article/details/130376168

目录

1. 背景

2. 线程安全问题

2.1 缓存不一致问题

2.2 CPU优化

2.3 内存屏障

3 Java内存模型


1. 背景

首先从为什么要有Java内存模型开始讲起。

  • 现在计算机往往都是多核的,每个核心下会有高速缓存。高速缓存的诞生是由于CPU和内存(主存)的速度存在差异,L1和L2缓存一般是每个核心独占一份的。
  • 为了让CPU提高运算效率,处理器可能会对输入的代码进行乱序执行,也就是指令重排序
  • 一次对数值的修改操作往往是非原子性的(比如i++实际上在计算机执行时会分成多个指令)。

总的来说,单线程下上面说的可见性、有序性、原子性都没问题,因为单线程意味着无并发,并且单线程下,编译器/runtime/处理器都必须遵守as-if-serial予以,意味着他们不会对数据依赖关系的操作做重排序。

CPU为了效率,有了高速缓存、指令重排序等,整个架构变得复杂,我们写程序的时候也需要充分利用CPU资源,所以不得不使用多线程。

2. 线程安全问题

多线程意味着并发,也就意味着需要考虑线程安全问题。

  • 缓存数据不一致:多个线程同时修改共享变量,CPU核心下的高速缓存是不同享的,那么cache与内存之间的数据同步怎么做?
  • CPU指令重排序在多线程下导致代码在非预期下执行,最终会导致结果存在错误的情况。

2.1 缓存不一致问题

1) 使用总线锁:某个核心在修改数据的过程中,其他核心均无法修改内存中的数据。(类似于独占内存的概念,只要有CPU在修改,那别的CPU就得等待当前CPU释放)

2) 缓存一致性协议(MESI):Modified(修改状态)、Exclusive(独占状态)、Share(共享状态)、Invalid(无效状态),根据对象状态做不同的策略,相较于总线锁,MESI的锁粒度更小了,所以性能会更高。

缓存一致性协议我认为可以理解为缓存锁,它针对的是缓存行进行加锁,所谓缓存行其实就是高速缓存存储的最小单位。

MESI协议的原理大概就是,当每个CPU读取共享变量之前,会先识别数据的对象状态(是修改、共享还是独占或者无效)。

  • 如果是独占,说明当前CPU将要得到的变量数据是最新的,没有被其他CPU所同时读取。
  • 如果是共享,说明当前CPU将要得到的变量数据还是最新的,有其他的CPU在同时读取,但没有被修改。
  • 如果是修改,说明CPU正在修改该变量的值,同时会向其他CPU发送该数据状态为Invalid的通知,得到其他CPU响应后(其他CPU将数据状态从共享变成Invalid),当前CPU将高速缓存的数据写到主存,并把自己的状态从从Modified变成Exclusive。
  • 如果是无效,说明当前数据是修改过的,需要从主存重新读取最新的数据。

2.2 CPU优化

MESI的关键在于某个CPU修改了数据时,需要同步通知其他CPU数据被修改了。

同步,意味着等待,所以CPU需要进行优化,也就是从同步变成异步。

在修改时同步告诉其他CPU,而现在则把最新修改的值写到Store Buffer中,并通知其他CPU要修改状态,随后CPU就直接返回干其他事情了,等接收到其他CPU的响应消息再将数据更新到高速缓存中。其他CPU接收到Invalid通知时,也会把接收到的消息放入Invalid queue就会直接返回告诉修改数据的CPU已经将状态修改为Invalid了。

1) 同核心读写共享变量问题

异步会带来新的问题,那我现在CPU修改完A值也写到Store Buffer了,CPU就可以干其他事情了,那如果CPU又接受指令需要修改A值但上一次修改的值还在Store Buffer中尚未修改至高速缓存呢?

所以CPU在读取时,需要去Store Buffer看看是否存在,存在则直接取,不存在才读主存的数据

2) 不同核心读写共享变量问题。

CPU1修改了A值,已经把修改后的值写到了Store Buffer并通知CPU2对该值进行Invalid操作,而CPU2可能还没收到Invalid通知就去做其他操作导致CPU2的还是旧值。

即便CPU2收到了Invalid通知,但CPU1的值还没写到主存所以CPU2再次想主存读取的时候也还是旧值。

总而言之,由于CPU对缓存一致性协议进行异步优化(Store Buffer、Invalid queue),很可能导致后面的指令查不到前面指令的执行结果(各个指令的执行顺序非代码执行顺序)。

2.3 内存屏障

为了解决乱序问题(可见性问题,也就是修改完没有及时同步到其他CPU),引出了内存屏障的概念。内存屏障其实就是把异步优化给禁用,分为三中类型:写屏障、读屏障、全能屏障

简单来说,屏障可以理解为在操作数据的时候往数据插入一条特殊指令,只要遇到这条指令,那前面的操作都得完成。

1) 写屏障

当CPU发现写屏障时,会把该指令之前存在于Store Buffer所有写指令刷入高速缓存,通过这种方式可以让CPU修改的数据可以立刻暴露给其他CPU,达到可见性的目的。

2) 读屏障

当CPU发现读屏障时,会把该指令之前存在于Invalid queue的所有指令都处理掉,通过这种方式确保当前CPU的缓存状态是正确的,于是读操作一定是读取最新的数据。

3) 全能屏障

包含了读屏障和写屏障,相当于读写屏障。

3 Java内存模型

由于不同CPU架构的缓存体系、缓存一致性协议、重排序策略不一样,提供的内存屏障指令也有差异,所以为了简化Java开发工作,Java封装了一套规范,也就是Java内存模型。

Java内存模型希望屏蔽各种硬件和操作系统的访问差异,保证了Java程序在各种平台下对内存的访问都能得到一致效果,目的是解决多线程存在的原子性、可见性和有序性问题。

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

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

相关文章

GoodSync 数据自动同步备份工具VS傲梅轻松备份系统数据备份工具 哪款更好?

备份和同步软件的使用越来越广泛,因为在这个数据驱动的时代,数据的备份和恢复非常重要。在这里我想向大家推荐两款备份和同步软件——GoodSync和傲梅轻松备份。 GoodSync是一款备份和同步软件,它可以在多个设备之间同步文件、文件夹、照片、音…

heic格式转化jpg的3种好用方法

如果你是使用iOS手机的用户,那么一定对HEIC格式不陌生。虽然HEIC格式可以保存原始图像质量,但它只能在苹果手机或Mac电脑上打开。如果我们想要在安卓或Windows系统上打开,就需要使用转换软件将HEIC格式转换成常用的JPG格式。HEIC 是一种新型的…

每日学术速递4.26

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.AutoNeRF: Training Implicit Scene Representations with Autonomous Agents 标题:AutoNeRF:使用自主代理训练隐式场景表示 作者:Pierre Marz…

macOS电脑

UNIX操作系统有一个规范,名叫《单一UNIX规范》(Single UNIX Specification)。凡是符合这个规范的操作系统都可以叫UNIX操作系统,并且可以通过UNIX官方认证。 UNIX商标认证官网是:The Register of UNIX Certified Prod…

Tuxera NTFS2023第三方应用苹果电脑磁盘读写工具

哪里有专业级的NTFS格式读写工具?Tuxera NTFS2023中文版是一款非常好用的NTFS读写工具,可以让您完整的读写兼容NTFS格式驱动器,对磁盘进行访问、编辑、存储和传输文件等操作。同时还包括开源磁盘管理器等简单的格式和硬盘维修检查和修复。Mac…

MySQL数据落盘原理(redo、undo、binlog、2PC、double write等。)

文章目录 前言一、架构图1、MySQL架构图2、InnoDB架构图 二、落盘分析1.第一阶段2.第二阶段3.第三阶段4.第四阶段5.第五阶段6.第六阶段 三、总结 前言 在上一章中我们聊到了事务有四大特性:原子性、一致性、隔离性、持久性。本篇文章就持久性重点聊一下&#xff0c…

【Feign扩展】OpenFeign日志打印Http请求参数和响应数据

SpringBoot使用log4j2 在Spring Boot中所有的starter 都是基于spring-boot-starter-logging的&#xff0c;默认使用Logback。使用Log4j2的话&#xff0c;你需要排除 spring-boot-starter-logging 的依赖&#xff0c;并添加 spring-boot-starter-log4j2的依赖。 配置依赖 <…

【小程序】input输入双向数据绑定

小程序中&#xff0c;input标签中的数据为单向绑定&#xff1a; <inputtype"number"bindinput"inputRealmoney"value"{{ amount }}"placeholder"请输入金额" />如上代码&#xff0c;我们绑定了输入框的数据amount&#xff0c;并…

Floccus插件 + 坚果云 实现不同浏览器间书签同步

&#xfeff; 在工作与学习中&#xff0c;我们时常希望在不同浏览器之间实现书签的同步&#xff1b;而一些传统的浏览器书签同步方案&#xff0c;或多或少都面临着一些问题——比如&#xff0c;Chrome浏览器尽管可以实现比较好的跨设备同步&#xff0c;但由于网络的限制可能导致…

多臂老虎机问题

1.问题简介 多臂老虎机问题可以被看作简化版的强化学习问题&#xff0c;算是最简单的“和环境交互中的学习”的一种形式&#xff0c;不存在状态信息&#xff0c;只有动作和奖励。多臂老虎机中的探索与利用&#xff08;exploration vs. exploitation&#xff09;问题一直以来都…

Java BIO

1.Java BIO(Blocking IO:同步并阻塞式IO)编程 1.1.基本介绍 1>.Java BIO就是传统的java io编程,其相关的类和接口在"java.io"包下; 2>.BIO(Blocking I/O): 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处…

centos配置nacos集群

nacos配置集群 1.官方文档地址 https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html 2.环境准备 1.64 bit OS&#xff0c;支持 Linux/Unix/Mac/Windows。&#xff08;至少3台&#xff0c;或者通过修改端口在一台服务器 启动多个nacos进行测试&#xff09;。 2.64 bit …

Three.js+TypeScript+Webpack学习记录(三)

使用环境参考 Node.js v16.19.1 正文 独立功能文件 我们不可能一直在 index.ts 中写代码&#xff0c;分离文件&#xff1a; // init.ts import * as THREE from threeexport const initScene () > {const scene new THREE.Scene()scene.background new THREE.Color(wh…

ChatGPT能用来写小说吗-gpt可以续写小说吗

怎么用ChatGPT写网文 ChatGPT是一个语言生成模型&#xff0c;可以用于生成各种文本&#xff0c;包括网文。下面是一些写网文的建议。 确定你的主题和情节。在开始写作之前&#xff0c;你需要确保你有一个明确的主题和情节&#xff0c;这可以帮助你更好地组织你的故事&#xff0…

电脑硬盘分区合并怎么操作?分享2个方法!

案例&#xff1a;电脑硬盘怎么分区&#xff1f; 【我把我的电脑硬盘分成了多个区域&#xff0c;这样可以方便存储和管理数据。现在我需要调整分区&#xff0c;对分区进行合并&#xff0c;但我不知道该如何操作&#xff0c;有没有小伙伴知道&#xff1f;】 在使用电脑的过程中…

【python视图3】networkx图操作示例

一、说明 根据定义&#xff0c;图是节点&#xff08;顶点&#xff09;以及已识别的节点对&#xff08;称为边、链接等&#xff09;的集合。在 NetworkX 中&#xff0c;节点可以是任何可哈希对象&#xff0c;例如文本字符串、图像、XML 对象、另一个图形、自定义节点对象等。 如…

perf生成火焰图

文章目录 1&#xff0c;top发现webserver进程空转情况下CPU占用高达200%2&#xff0c;使用性能分析工具perf来进行分析2.1&#xff0c;抓取采集样本2.2&#xff0c;使用perf简单分析性能数据 3&#xff0c;火焰图3.1&#xff0c;生成火焰图3.2&#xff0c;将生成的.svg文件用浏…

Chapter 4 :Constraining I/O Delay(ug903)

4.1 About Constraining I/O Delay 要在设计中准确地建模外部时序上下文&#xff0c;必须为输入和输出端口提供时序信息。由于XilinxVivado集成设计环境&#xff08;IDE&#xff09;只能识别FPGA边界内的时序&#xff0c;因此必须使用以下命令来指定超出这些边界的延迟…

数据库系统工程师——第五章 网络基础知识

文章目录 &#x1f4c2; 第五章、网络基础知识 &#x1f4c1; 5.1 计算机网络概述 &#x1f4d6; 5.1.1 计算机网络的概念 &#x1f4d6; 5.1.2 计算机网络的分类 &#x1f4d6; 5.1.3 网络的拓扑结构 &#x1f4c1; 5.2 网络硬件基础 &#x1f4d6; 5.2.1 网络设备 &…

【k8s】ruoyi微服务迁移到k8s

书接上回【传统方式部署Ruoyi微服务】&#xff0c;此刻要迁移至k8s。 环境说明 31 master &#xff0c; 32 node1 &#xff0c; 33 node2迁移思路 交付思路: 其实和交付到Linux主机上是一样的&#xff0c;无外乎将这些微服务都做成了Docker镜像; 1、微服务数据层: MySQL、 R…