当前位置:首页 > 内存 > 正文

java虚拟机内存模型

  • 内存
  • 2024-05-11 14:35:02
  • 9265

一、Java内存区域划分、内存分配原理是什么?

Java虚拟机运行Java程序时,会将其管理的内存划分为不同的数据区域。这些区域都有自己的目的,以及创建和破坏的时间。有些区域随着虚拟机进程的启动而存在,有些区域根据用户线程的启动和结束而建立和销毁。根据《Java虚拟机规范(第2版)》

Java虚拟机管理的内存将包括以下运行时数据区域,如下:


二、Java内存模型详解Java内存模型:深入解析与实例分析

在Java并发编程的世界里,通信和同步是核心要素。Java内存模型主要基于共享内存。每个线程都有自己的本地内存,共享变量存储在主内存中。通过Java内存模型(JMM)精确控制线程之间的通信,以确保本地内存更新及时与主内存同步,并且其他线程可以读取最新状态。编译器和处理器重新排序行为可能会给内存可见性带来挑战。JMM通过一系列规则巧妙地管理这些复杂性,以确保内存一致性。


直观地理解,当线程A更新共享变量x时,这个变化会被JMM从本地内存刷新到主内存,然后线程B会读取这个更新后的值。基本上内存模型是如何工作的。


重排序现象分为编译器优化、指令级并行和内存系统重排序,这可能会导致多线程中出现微妙的问题。JMM使用细粒度规则(例如StoreLoad屏障)来管理和禁止可能导致问题的特定重新排序。例如,StoreLoad屏障确保内存访问顺序的全局一致性,即使在多处理器架构中也是如此。


内存模型的关键概念

JMM作为语言级抽象来确保跨多个平台的内存可见性。处理器重新排序可能会导致内存操作以与预期不同的顺序执行。现代处理器允许存储加载重新排序,但sparc-TSO和x86处理器有严格的限制。编译器通过插入内存屏障指令(例如LoadLoad、StoreStore、LoadStore和StoreLoad屏障)来保持一致性,这些指令是最全面的,可确保内存操作的顺序一致性,尽管这可能会增加处理成本。


JSR-133引入了happens-before的概念,它定义了操作之间的内存可见性。此概念不要求操作按特定顺序执行,但要求先前的操作对后续操作可见。发生在关系与JMM相关联,简化了理解如何重新组织内存的复杂性。数据依赖关系有三种类型,编译器和处理器遵循这些规则来保证单线程程序的执行顺序不改变。


重新排序和多线程示例

在多线程编程中,重新排序可能会破坏线程B读取的共享变量值,尤其是在线程A更新之后。控制依赖性可能会导致处理器执行推测执行,这可能会导致多线程处理中出现意外结果。正如SynchronizedExample中所示,JMM确保正确同步的代码遵循顺序一致性,这意味着所有线程看到的操作顺序保持一致。


JMM通过强制互斥来限制关键部分的重新排序,同时允许编译器和处理器执行性能优化。对于未正确同步的程序,JMM提供基本的内存可见性保证,但不保证完全符合顺序一致性模型。这些差异体现在单线程操作的顺序、long/double类型的原子性以及处理器总线机制可能导致的非原子读写上。


关于内存可视化,例如计算圆面积的示例,JMM确保与内存操作相关的代码对所有流产生一致的结果。JMM的简要概述如下:


在环形区号中,其对应关系为A->B、B->C。在不影响结果的情况下,JMM强调这些关系对于理解记忆模型很重要。
JMM区分了影响性能结果的重排序和允许必须禁止优化的重排序,而重排序允许性能优化的同时保证一致性。
JMM设计方案强调其简单性,确保内存可见性以及对编译器和处理器的最小约束。

内存可见性的核心价值在于正确同步的代码可以保证执行结果的一致性,无论是单线程还是多线程流。同时,JMM对不完全同步的场景提供了基础的保护,保证不会出现毫无根据的问题。


最后,JSR-133引入的volatile和final关键字增强了内存可见性并确保代码正确性和安全初始化。总体而言,Java内存模型是一种平衡,旨在满足程序员的编程需求,同时保持与编译器和处理器优化的兼容性。