Java内存模型(Java Memory Model,JMM)

简介: Java内存模型(Java Memory Model,JMM)


今天简单聊聊什么叫做 Java 内存模型,不是 JVM 内存结构哦。

JMM 是一个语言级别的内存模型,处理器的硬件模型是硬件级别,Java中的内存模型是内存可见性的基本保证。从而为我们 volatile 实现内存可见性提供了基石。主要目的就是让 Java 程序员在各种平台下达到一致性访问效果

JMM决定一个线程对共享变量的写入何时对另一个线程可见,尤其是在对共享变量的读写,修改后其他线程立刻内读取到,这个就是JMM主要作用。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。Java内存模型的抽象示意如图所示。

image.png

前面我们说到 volatile 底层原理详解,这个语义的实现就是利用了Java的内存模型。为我们屏蔽了细节,实现了内存可见性,有兴趣的读者可以看公众号前期发的文章 volatile 底层原理实现

为什么需要JMM?

1. 从源代码到指令序列的重排序

在执行程序的时候,为了提高性能,编译器与处理器常会对指令进行重排序优化,保证执行结果与书序执行的结果是一致的,但并不能保证各个语句执行的先后顺序与输入的代码顺序一致。(当然是说在单线程的情况下)。

所以有 volatile 修饰的代码就不会被指令重排,相当于加了一道内存屏障,不能把后面的指令重排序到内存屏障之前。

2. Happens-before原则(先行发生)

Happens-before定义:

  • 如果一个操作 Happens-before 另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序在第二个操作之前。
  • 两个操作之间存在 Happens-before 关系,并不意味着必须按照代码指定顺序执行。如果重排序后的执行结果与按照 Happens-before 结果执行的结果一致,那也是可以的。

先行发生是 Java 内存模型中定义的两项操作之间的偏序关系,如果说操作A先行发生于B,其实就是说在发生操作 B 之前,操作 A 产生的影响能被 B 观察到, “影响” 包括修改了内存中共享变量的值、发送了消息、调用了方法。比如:

//在线程 A 执行  1
i =  2;`
// 在线程 B 执行   2
j = i;`
// 在线程 C 执行   3
i =  3;
  • 假设执行顺序是 1 -> 3 -> 2:那么 j 的值是 3。
  • 假设执行顺序是 1 -> 2 -> 3:那么 j 的值是 2。

若我们想要按照 1 ,2 ,3顺序执行。那么只有同步才能保证一致性。

总而言之:

  • 通过JMM内存模型,volatile 内存可见性的实现才得以保证。但是又不需要我们去关注不同平台的细节。当对一个 volatile 修饰的变量修改是,JMM 会把该线程对应的本地内存中的共享变量刷新到主内存中。
  • 当读一个 volatile 变量的时候, JMM 会把该线程对应的本地内存设置无效,并从主内存中读取共享变量。
  • volatile 在满足 Happens-before原则情况下,禁止指令重排序。
相关文章
|
3月前
|
存储 缓存 安全
Java内存模型深度解析:从理论到实践####
【10月更文挑战第21天】 本文深入探讨了Java内存模型(JMM)的核心概念与底层机制,通过剖析其设计原理、内存可见性问题及其解决方案,结合具体代码示例,帮助读者构建对JMM的全面理解。不同于传统的摘要概述,我们将直接以故事化手法引入,让读者在轻松的情境中领略JMM的精髓。 ####
54 6
|
2月前
|
安全 Java 程序员
深入理解Java内存模型与并发编程####
本文旨在探讨Java内存模型(JMM)的复杂性及其对并发编程的影响,不同于传统的摘要形式,本文将以一个实际案例为引子,逐步揭示JMM的核心概念,包括原子性、可见性、有序性,以及这些特性在多线程环境下的具体表现。通过对比分析不同并发工具类的应用,如synchronized、volatile关键字、Lock接口及其实现等,本文将展示如何在实践中有效利用JMM来设计高效且安全的并发程序。最后,还将简要介绍Java 8及更高版本中引入的新特性,如StampedLock,以及它们如何进一步优化多线程编程模型。 ####
43 0
|
2月前
|
安全 Java 程序员
Java内存模型的深入理解与实践
本文旨在深入探讨Java内存模型(JMM)的核心概念,包括原子性、可见性和有序性,并通过实例代码分析这些特性在实际编程中的应用。我们将从理论到实践,逐步揭示JMM在多线程编程中的重要性和复杂性,帮助读者构建更加健壮的并发程序。
|
3月前
|
Java
Java内存模型
JMM(Java内存模型 )屏蔽了各种硬件和操作系统的内存访问差异,实现让Java程序在各平台下都能达到一致的内存访问效果,它定义了JVM如何将程序中的变量在主存中读取 具体定义为:所有变量都存在主存中,主存是线程共享区域;每个线程都有自己独有的工作内存,线程想要操作变量必须从主从中copy变量到自己的工作区,每个线程的工作内存是相互隔离的 由于主存与工作内存之间有读写延迟,且读写不是原子性操作,所以会有线程安全问题
|
2月前
|
存储 缓存 数据安全/隐私保护
DMA(Direct Memory Access):直接内存访问
DMA(Direct Memory Access)是一种允许外设直接与内存进行数据传输的技术,无需 CPU 干预。它通过减轻 CPU 负担、提高数据传输效率来提升系统性能。DMA 的工作模式包括直接模式和 FIFO 模式,数据传输方式有单字传送和块传送,寻址模式有增量寻址和非增量寻址。通过缓存一致性协议、同步机制、数据校验和合理的内存管理,DMA 确保了数据在内存中的一致性和完整性。
108 0
|
3月前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
65 6
|
3月前
|
存储 缓存 安全
Java内存模型(JMM):深入理解并发编程的基石####
【10月更文挑战第29天】 本文作为一篇技术性文章,旨在深入探讨Java内存模型(JMM)的核心概念、工作原理及其在并发编程中的应用。我们将从JMM的基本定义出发,逐步剖析其如何通过happens-before原则、volatile关键字、synchronized关键字等机制,解决多线程环境下的数据可见性、原子性和有序性问题。不同于常规摘要的简述方式,本摘要将直接概述文章的核心内容,为读者提供一个清晰的学习路径。 ####
55 2
|
3月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
544 1
|
2月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
3月前
|
Java
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80