详说Java内存模型(JMM)

article/2025/10/5 15:56:49

文章目录

  • 什么是Java内存模型
  • 为什么提出内存模型
  • Java主内存与工作内存
  • JMM三大特性
    • 可见性
    • 有序性
    • 原子性
  • 并发总结

什么是Java内存模型

Java内存模型就是(Java Memory Model),它规范了Java虚拟机与计算机内存是如何协同工作的。Java虚拟机就是一个完整的计算机的模型,因此这个模型自然也包含了一个内存模型——就称为Java内存模型。

通俗来说,JMM是一套多线程读写共享数据时,对数据的可见性有序性原子性的规则。

为什么提出内存模型

在硬件的发展当中,一直都存在着一个矛盾,在CPU、内存、I/O设备的速度差异。

默认的排序为:CPU > 内存 > I/O设备

所以为了平衡这三者的速度差异,就做了一写优化:
在CPU中添加寄存器,以均衡内存与CPU之间的差异;
操作系统以线程又分为复用CPU,进而均衡I/O设备与CPU的速度差异;
编译程序优化指令执行次序,使得缓存能够得到更加合理地利用。

Java主内存与工作内存

接下来,先看看线程在执行的时候,对数据的拿去。

Java内存模型(JMM)的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量(线程贡献的变量)存储到电脑内存和内存中取出变量的底层细节。

Java内存模型中规定了所有的变量都是存储在主内存(电脑内存)中,但每条线程还有着自己的工作内存,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。

这里的工作内存就是JMM的一个抽象概念,也就做本地内存,其中存储了该线程的读/写贡献变量的副本。

就像每个处理器内核都拥有自己私有的本地内存,同理在JMM中每个线程都拥有自己的本地内存

在不同的线程之间是无法通过直接访问对方工作内存中的变量,线程间的通信一般有两种方式进行,一是通过消息传递、而是内存共享。
Java线程间的通信采用的是共享内存的方式,线程,主内存和工作内存之间的交互。
在这里插入图片描述

在这里所说的主内存、工作内存是与Java内存区域中的堆、栈、方法区等并不是在同一个层次的内存划分,这两个基本是没有是关系的。如果非要说两个一定要面前对象起来的haul,那从变量、主内存、工作内存的定义来看,主内存主要对应于Java堆中的对象实例数据部分,而工作内存则对应于虚拟机栈中的部分区域。

JMM三大特性

可见性

就是一个线程对共享变量的修改,另外一个线程能立刻看到,我们就称为可见性。

对于现在的多核处理器,没课CPU都是拥有自己的缓存的,但这个缓存是仅仅对它所在的处理器是可见的,但CPU缓存与主内存的数据是很难保持一致性的。

为了避免处理器停顿下来等待向内存写入数据而产生的延迟,处理器就会使用写缓冲区来临时保存向内写入的数据。写缓冲区合并对同一内存地址的多次写,并以批处理的方式进行刷新,也就是说写缓冲区不会即时将数据刷新到主内存中。

一句话总结一下:多核的CPU,每个内核中都会有一个高速缓存,在每个高速缓存当中的数据在线程之间都是不可见的。

有序性

有序性指的是程序按照代码的先后顺序进行执行

为了优化性能,有时候会改变程序中语句的先后顺序。

CPU的读等待同时指令执行是CPU乱序的根源。

读指令的同时可以同时执行不影响的其他指令。

对于一个线程的代码而言,我们总是以为代码的执行是从前往后的,依次执行的。这么说不能说完全不对,在单线程程序里,确实会这样执行;
但是在多线程并发时,程序的执行就有可能出现乱序。
用一句话可以总结为:在本线程内观察,操作都是有序的;如果在一个线程中观察另外一个线程,所有的操作都是无序的。前半句是指“线程内表现为串行语义(WithIn Thread As-if-Serial Semantics)”,后半句是指“指令重排”现象和“工作内存和主内存同步延迟”现象

原子性

这是线程切换所带来的原子性问题

原子的意思就是“不可分”;
一个或多个操作在CPU执行的过程中不被中断的特性,我们就称为原子性。

原子性是拒绝多线程交互操作的,不论是多核和单核,具有原子性的量,同一时刻只能有一个线程来对它进行操作。

CPU能保证的原子操作是CPU指令级别的,而不是高级语言的操作符。线程切换就会导致原子性问题。

说具体一点就是:一个操作不能被打断,要么全部执行完毕,要么不执行。在这点上有点类似于MyBatis中的事务操作,要么全部执行成功,要么回退到执行该操作之前的状态。

举个例子:
一个最经典的例子就是银行汇款问题,一个银行账户存款100,这时一个人从该账户取10元,同时另一个人向该账户汇10元,那么余额应该还是100。那么此时可能发生这种情况,A线程负责取款,B线程负责汇款,A从主内存读到100,B从主内存读到100,A执行减10操作,并将数据刷新到主内存,这时主内存数据100-10=90,而B内存执行加10操作,并将数据刷新到主内存,最后主内存数据100+10=110,显然这是一个严重的问题,我们要保证A线程和B线程有序执行,先取款后汇款或者先汇款后取款。要保证其有序性


举个例子
在Java当中并发程序都是基于多线程的,自然也会涉及到任务切换,任务切换的时机大多数是在时间片结束的时候。

我们现在基本都使用高级语言编程,高级语言里一条语句往往需要多条CPU指令完成。

举一个例子。i++操作:在CPU中就需要三条指令才能完成。

在这要求执行两次i ++
在这里插入图片描述

但是因为线程之间不遵守原子性,且两线程之间是不可见性的。
所以在执行的时候会出现一些问题,造成结果为1,在指令3中,最后同时给主内存当中写入数据为1。使得和我们想要的结果出现了偏差。

所以在这也说明了i++其实是线程不安全的。

并发总结

缓存可见性问题,编译优化带来的有序性问题,线程切换带来的原子性问题。其实缓存、线程、编译优化的目的和我们写并发编程的目的是相同的,都是提高程序安全性和性能。但是技术在解决第一个问题的同时,必须会带来另外一个问题,所以在采用一项技术的同时,一定要清除它带来的问题是什么,以及如何规避。

实现可见性和有序性是volatile关键字来实现的。
实现原子性是依靠锁机制来实现的。


下一篇:===》volatile关键字实现可见性和有序性

下一篇:===》锁机制实现线程并发的原子性


http://chatgpt.dhexx.cn/article/KydtVZxv.shtml

相关文章

详解Java内存模型

文章目录 一、简介二、处理器、高速缓冲、主内存间的交互关系三、Java线程、工作内存和主内存的交互关系四、8大原子操作五、8大Happens-Before原则 一、简介 Java内存模型(JMM)是线程间通信的控制机制,JMM定义了主内存和线程工作内存之间的抽…

Java内存模型的一点理解

关于Java内存模型的问题 文章目录 前言一、Java内存模型二、其中一些指向问题1.内存指向问题为什么? 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要…

【Java】Java内存模型

1.什么是Java内存模型 Java内存模型(Java Memory Model,JMM)是一种抽象的,不存在的概念。是一种屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。 Java内…

2.什么是JAVA内存模型?

为什么要设计JAVA内存模型? 小陈:老王,看了上一篇的《CPU多级缓存模型》,有个疑问为什么还要有JAVA内存模型啊? 老王:这么来说吧,CPU多级缓存模型,只是一个规范,但是底层…

Java内存模型是什么

网上有很多关于Java内存模型的文章,在《深入理解Java虚拟机》和《Java并发编程的艺术》等书中也都有关于这个知识点的介绍。但是,很多人读完之后还是搞不清楚,甚至有的人说自己更懵了。本文,就来整体的介绍一下Java内存模型&#…

Java内存模型是什么,为什么要有Java内存模型,Java内存模型解决了什么问题等。。。

本文中,有很多定义和说法,都是笔者自己理解后定义出来的。希望能够让读者可以对Java内存模型有更加清晰的认识。当然,如有偏颇,欢迎指正。 为什么要有内存模型 在介绍Java内存模型之前,先来看一下到底什么是计算机内存…

Java内存模型相关面试题

一、谈谈你对Java内存模型的理解可以吗? 对于Java内存模型大家千万不能和JVM内存模型弄混了,不一样的; JVM内存模型是指JVM的内存分区,就是JVM分了几个区域;而Java内存模型是一种虚拟机规范。 首先来看下面一段代码&…

什么是Java内存模型?

点击上方“程序员小灰”,选择“置顶公众号” 有趣有内涵的文章第一时间送达! 本文转载自公众号 占小狼的博客 说”JVM内存模型“,有人会说是关于JVM内存分布(堆栈,方法区等)这些介绍,也有地方说…

Java面试--Java内存模型

面试题:你了解Java内存模型吗?(顺丰面试题) 面试题:程序内存的分布,五个部分(360面试题) 一、Java程序的执行过程: Java源代码文件(.java后缀)会被Java编译器编译为字节码文件(.class后缀),然后由JVM中…

JAVA内存模型与JVM内存模型

JAVA内存模型(JMM)与JVM内存模型 1、JAVA内存模型保证了在多线程环境下,对共享变量读写的原子性、可见性和有序性的一系列规范。 2、JVM内存模型规定了JAVA虚拟机在运行时使用的内存的各个分区及其作用。JAVA内存模型 原子性: 通过 synchronized、lock实现&#x…

Java内存模型(JMM)详解

目录 一、为什么要有内存模型二、CPU和缓存一致性2.1 为什么需要CPU cache2.2 三级缓存(L1、L2、L3)2.3 乱序执行优化 三、java内存模型3.1 JVM对Java内存模型的实现3.2 Java内存模型和硬件架构之间的桥接3.3 Java内存模型 - 同步八种操作3.4 Java内存模…

jvm内存模型和java内存模型

初识java虚拟机,就碰到一系列不懂的问题。我们以前常说java把局部变量放在栈里,new出来的变量放在堆里,然后堆里的数据不定时就给回收了。然后,如果是多线程的话,每个线程自己都有会一个私有的虚拟机栈,运行…

JAVA内存模型与JVM内存模型的区别

** JAVA内存模型与JVM内存模型的区别 ** 直接进入正题 **JAVA内存模型: Java内存模型规定所有的变量都是存在主存中,每个线程都有自己的工作内存。线程堆变量的操作都必须在工作内存进行,不能直接堆主存进行操作,并且每个线程…

【3】Java内存模型

目录 知识点1:Java内存模型 知识点2:Volatile 1、什么是Volatile 2、Volatile特性 3、Volatile与Synchronized区别 知识点3:重排序 1、数据依赖性 2、as-if-serial语义 3、程序顺序规则 4、重排序对多线程的影响 知识点1&#xff1a…

Java内存模型详解

文章目录 一、什么是JMM?为什么需要JMM?二、JMM 如何抽象线程和主内存之间的关系?三、Java 内存区域和 JMM 有何区别?四、happens-before原则五、总结 一、什么是JMM?为什么需要JMM? Java 是最早尝试提供内…

java内存模型概述

java内存模型 为了控制线程之间的通信,(完成底层封装) 用来屏蔽掉各种硬件和操作系统之间的内存访问差异,以实现让Java程序在各平台下都能达到一致的内存访问效果。 JMM目标:定义程序中各个变量的访问规则&#xff0c…

理解Java内存模型(JMM)

本篇的写作思路是先阐明Java内存区域划分、硬件内存架构、Java多线程的实现原理与Java内存模型的具体关系,在弄明白它们间的关系后,进一步分析Java内存模型作用以及一些实现手段 理解Java内存区域与Java内存模型 Java内存区域 Java虚拟机在运行程序时会…

Java 内存模型

Java 内存模型(Java Memory Model),简称 JMM。 JVM 中试图定义一种 JMM 来屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。 一、物理内存模型 物理机遇到的并发问题与虚拟机中…

Java内存模型

Java内存模型 1.内存模型概念图2.线程共享区方法区常量池运行时常量池全局字符串池class文件常量池 堆空间3.线程独占区虚拟机栈本地方法栈程序计数器 4.对象的创建 1.内存模型概念图 2.线程共享区 方法区 方法区也是线程共享区用于储存虚拟机加载的类信息(类的版…

一文看懂Java内存模型(JMM)

文章目录 Java内存模型介绍总览图Java内存模型图线程、主内存、工作内存关系图CPU缓存架构图Java内存模型与硬件内存架构的关系 什么是Java内存模型Java内存模型的意义Java内存模型规范 Java内存模型的主要结构1、程序计数器(Program Counter Register)2…