当前位置: 首页 > article >正文

JMM:Java内存模型

Java内存模型(JMM)

参考:https://javaguide.cn/java/concurrent/jmm.html、https://www.javabetter.cn/thread/jmm.html

JMM 是什么?

JMM(Java Memory Model)出现的原因有两点(如下)。所以,才需要JMM 规定内存可见性规则和禁止特定的指令重排序,保证不同线程能看到正确的共享数据状态,实现多线程之间的正确交互

  1. 因为在不同的操作系统上,内存模型不同。如果直接使用操作系统的内存模型,就违背了Java的跨平台特性。所以,Java语言才会制定JMM。
  2. JMM制定一套规范,确保在多线程环境下数据的一致性、支持高效的同步机制

这里主要讲一下为什么会有多线程安全问题:指令重排

指令重排

为了提升执行速度,计算机在执行程序代码的时候,会对指令进行重排序(即不一定按照写的代码顺序执行)。常见的 指令重排有两种:

  1. 编译器优化重排:编译器(包括 JVM、JIT 编译器等)在不改变单线程程序语义的前提下,重新安排语句的执行顺序。
  2. 指令并行重排:现代处理器采用了指令级并行技术(Instruction-Level Parallelism,ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。

指令重排序可以保证串行语义一致,但是没有义务保证多线程间的语义也一致,所以在多线程下,指令重排序可能会导致一些问题。解决办法:

  1. 对于编辑器,通过禁止编译器重排序,可禁止重排序。

  2. 对于处理器,通过插入内存屏障(Memory Barrier,或有时叫做内存栅栏,Memory Fence)的方式来禁止特定类型的处理器重排序。

    内存屏障是一种 CPU 指令,用来禁止处理器指令发生重排序(像屏障一样),从而保障指令执行的有序性。

JMM 工作原理

Java 内存模型(JMM) 抽象了线程和主内存之间的关系,就比如说线程之间的共享变量必须存储在主内存中

首先,JMM 中的内存模型中,分为主内存、工作内存:

  • 主内存:Java内存模型规定了所有的共享变量都存储在主内存中。

  • 工作内存(本地内存):每个线程都有一个私有的工作内存,线程的工作内存中保存了该线程中使用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行

    在这里插入图片描述

多线程下,对主内存的共享变量进行操作会诱发线程安全问题。而 JMM 定义了一系列的操作来保证线程的同步问题,他规定了如何做数据同步以及什么时候做数据同步

JVM 内存结构 和 JMM 的区别

  • JMM 主要关注的是多线程编程中的并发控制问题,通过一系列规范来保证数据的一致性和可见性。例如,Happens-before规则用于确保某些操作的顺序性。
  • JVM内存结构 则更多地涉及具体的内存管理策略,如内存区域的划分垃圾回收机制等,这些都直接影响到程序的性能和运行效率。

JMM 与 happens-before 原则?

虽然JMM提供了一个强大的内存模型,保证多线程之间的正确交互。但是另外一方面 编译器、处理器 又希望 JMM 的束缚少一点,这样就可以尽可能的做更多优化。JMM 提供了happens-before 规则,来达到一定的平衡。

happens-before 关系的定义:如果一个操作 happens-before 另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前


http://www.kler.cn/news/312654.html

相关文章:

  • Python 中的异步编程:从入门到实践
  • gRPC介绍
  • LeetCode: 197. 上升的温度
  • 105.WEB渗透测试-信息收集-FOFA语法(5)
  • 动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
  • 计算机网络各层有哪些协议?
  • Ubuntu 软件仓库镜像使用帮助
  • js中【argument】知识点详解
  • 低级编程语言和高级编程语言
  • Linux 开发工具篇(〇)yum
  • The application may be doing too much work on its main thread.
  • T9-猫狗识别2(暂时版qaq)
  • 《深度解析 C++中的拷贝构造函数:概念、作用与实践》
  • STM32F1+HAL库+FreeTOTS学习11——延时函数API
  • QT的dropEvent函数进入不了
  • 平滑损失对生成图像的影响和使用场景
  • 跟着DAMA学数据管理--数据管理框架
  • 身份证实名认证的应用场景-身份证识别api
  • 人工智能安全治理新篇章:《2024人工智能安全治理框架1.0版》深度解读@附20页PDF文件下载
  • cas 5.3服务器搭建
  • 【busybox记录】【shell指令】stdbuf
  • MySQL —— 索引
  • C++ | Leetcode C++题解之第407题接雨水II
  • Windows下SDL2创建最简单的一个窗口
  • 华为昇腾服务器+Atlas300IPro*2 部署Dify+MindIE+Embedding+Rerank实现Qwen2.5-7B全国产化的大模型推理平台
  • stm32f411ceu6芯片学习
  • CSP-J 算法基础 归并排序
  • VideoPlayer插件的用法
  • 初体验《SpringCloud 核心组件Eureka》
  • 栈的各种接口的实现(C)