首页 > 系统相关 >Java内存模型原理,你真的理解吗?(转载)

Java内存模型原理,你真的理解吗?(转载)

时间:2023-05-11 16:12:47浏览次数:33  
标签:缓存 Java 运算 模型 内存 转载 处理器

内存模型产生背景

在介绍 Java 内存模型之前,我们先了解一下物理计算机中的并发问题,理解这些问题可以搞清楚内存模型产生的背景。

物理机遇到的并发问题与虚拟机中的情况有不少相似之处,物理机的解决方案对虚拟机的实现有相当的参考意义。

物理机的并发问题

硬件的效率问题

计算机处理器处理绝大多数运行任务都不可能只靠处理器“计算”就能完成,处理器至少需要与内存交互,如读取运算数据、存储运算结果,这个 I/O 操作很难消除(无法仅靠寄存器完成所有运算任务)。

由于计算机的存储设备与处理器的运算速度有几个数量级的差距,为了避免处理器等待缓慢的内存完成读写操作,现代计算机系统通过加入一层读写速度尽可能接近处理器运算速度的高速缓存。

缓存作为内存和处理器之间的缓冲:将运算需要使用到的数据复制到缓存中,让运算能快速运行,当运算结束后再从缓存同步回内存之中。 

缓存一致性问题

基于高速缓存的存储系统交互很好的解决了处理器与内存速度的矛盾,但是也为计算机系统带来更高的复杂度,因为引入了一个新问题:缓存一致性。

在多处理器的系统中(或者单处理器多核的系统),每个处理器(每个核)都有自己的高速缓存,而它们有共享同一主内存(Main Memory)。

当多个处理器的运算任务都涉及同一块主内存区域时,将可能导致各自的缓存数据不一致。 

为此,需要各个处理器访问缓存时都遵循一些协议,在读写时要根据协议进行操作,来维护缓存的一致性。

代码乱序执行优化问题

为了使得处理器内部的运算单元尽量被充分利用,提高运算效率,处理器可能会对输入的代码进行乱序执行。

处理器会在计算之后将乱序执行的结果重组,乱序优化可以保证在单线程下该执行结果与顺序执行的结果是一致的,但不保证程序中各个语句计算的先后顺序与输入代码中的顺序一致。

乱序执行技术是处理器为提高运算速度而做出违背代码原有顺序的优化。在单核时代,处理器保证做出的优化不会导致执行结果远离预期目标,但在多核环境下却并非如此。

在多核环境下, 如果存在一个核的计算任务依赖另一个核计算任务的中间结果。

而且对相关数据读写没做任何防护措施,那么其顺序性并不能靠代码的先后顺序来保证,处理器最终得出的结果和我们逻辑得到的结果可能会大不相同。

以上图为例进行说明,CPU 的 core2 中的逻辑 B 依赖 core1 中的逻辑 A 先执行:

  • 正常情况下,逻辑 A 执行完之后再执行逻辑 B。

  • 在处理器乱序执行优化情况下,有可能导致 flag 提前被设置为 true,导致逻辑 B 先于逻辑 A 执行。

Java 内存模型的组成分析

内存模型概念

为了更好解决上面提到的系列问题,内存模型被总结提出,我们可以把内存模型理解为在特定操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象。

不同架构的物理计算机可以有不一样的内存模型,Java 虚拟机也有自己的内存模型。

Java 虚拟机规范中试图定义一种 Java 内存模型(Java Memory Model,简称 JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果,不必因为不同平台上的物理机的内存模型的差异,对各平台定制化开发程序。

更具体一点说,Java 内存模型提出目标在于,定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。

此处的变量(Variables)与 Java 编程中所说的变量有所区别,它包括了实例字段、静态字段和构成数值对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的。

注:如果局部变量是一个 reference 类型,它引用的对象在 Java 堆中可被各个线程共享,但是 reference 本身在 Java 栈的局部变量表中,它是线程私有的。

Java 内存模型的组成

主内存

Java 内存模型规定了所有变量都存储在主内存(Main Memory)中(此处的主内存与介绍物理硬件的主内存名字一样,两者可以互相类比,但此处仅是虚拟机内存的一部分)。

工作内存

每条线程都有自己的工作内存(Working Memory,又称本地内存,可与前面介绍的处理器高速缓存类比),线程的工作内存中保存了该线程使用到的变量的主内存中的共享变量的副本拷贝。

工作内存是 JMM 的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。

Java 内存模型抽象示意图如下:

 

标签:缓存,Java,运算,模型,内存,转载,处理器
From: https://www.cnblogs.com/grassLittle/p/17391328.html

相关文章

  • java基础语法
    JAVA基础语法注释单行注释://System.out.println("Helloworld");多行注释:/*System.out.println("Helloworld");System.out.println("Helloworld");System.out.println("Helloworld");*/文档注释:/***@Descr......
  • java 启动参数设置
    nohupjava-Xms512m-Xmx1024m-XX:PermSize=64m-XX:MaxPermSize=512m-jarxxx.jar>>xxx.out2>&1&java虚拟机对外提供的可配置堆区的参数1、-Xms:表示java虚拟机堆区内存初始内存分配的大小,通常为操作系统可用内存的1/64大小即可,但仍需按照实际情况进行分配。有可能真的按......
  • Java生成微信小程序码
    官网文档地址:获取小程序码packagetest;importcom.alibaba.fastjson.JSONObject;importcom.fasterxml.jackson.core.JsonProcessingException;importcom.fasterxml.jackson.databind.ObjectMapper;importorg.apache.http.HttpEntity;importorg.apache.http.client.met......
  • java代码中fastjson生成字符串和解析字符串的方法和javascript文件中字符串和json数组
    1.java代码中fastjson生成字符串和解析字符串的方法List<TemplateFull>templateFulls=newArrayList<TemplateFull>();JSONArrayjsonArr=newJSONArray();jsonArr.addAll(templateFulls);StringjsonStr=jsonArr.toJSONString();System.out.pr......
  • java代理模式及动态代理类
    1.     代理模式代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式一般涉及到的角色有:抽象角色:声明真实对象和代理对象的共同接口;代理角色:......
  • JavaWeb之Servlet本质
    Servlet:服务器和Wepapp开发者之间的协议,sun公司已经规范了Servlet协议,Wepapp开发者只需要去实现规范接口类和对应的配置文件即可,Servlet底层是面向接口编程,用反射机制实例化一个类后再向下转型成Servlet类(因为Wepapp开发者实现规范好,只需到对应的文件中调用各个方法)菜鸟教程的解......
  • Java 9模块化关键字及应用场景
    一、背景SpringBoot3.0最低要求jdk17,为跟上节奏储备知识。二、简介关键字描述应用场景module定义一个模块代码隔离,依赖控制,代码可重用性openmodule定义一个像java9之前的开放模块像Java的旧版本那样允许完全反射exports...to指定模块的一部分对外提供......
  • Java 服务 CPU 占用过高排查
    先需要找出那个进程占用CPU高。top列出系统各个进程的资源占用情况。然后根据找到对应进行里哪个线程占用CPU高。top-Hp进程ID列出对应进程里面的线程占用资源情况找到对应线程ID后,再打印出对应线程的堆栈信息printf"%x\n"PID把线程ID转换为16进制。......
  • Linux重启Java的.sh脚本shell
    原文链接:https://blog.csdn.net/weixin_44821965/article/details/130039771前言最近看到了项目中重启Java服务的.sh文件,对sh文件里面的命令产生了好奇,于是研究了一下脚本里面每一个命令的具体意义一、.sh文件内容.sh文件里面的内容如下:ps-ef|grepplugins-web|grep-vgre......
  • Java---内部类
    Java---内部类内部类的概念内部类就是一个类内部包含另一个类分类:成员内部类局部内部类(包含匿名内部类)格式:修饰符class外部类名称{修饰符class内部类名称{//}}注意:内用外,随意访问;外用内,需要内部类对象.代码示例publicclassBody{privateSt......