Java内存模型(Memory Model)

Java内存模型(Memory Model)

  

  Java内存模型,Java Memory Model,我个人更喜欢“Java存储模型”的译法。

  介绍

  如前所述,JVM被设计成一台抽象的虚拟计算机,JVM的并发问题及解决方案与物理计算机中的并发问题有很多相似之处。

  由于现代计算机的内存与CPU在运算速度上的巨大差别,通常会加入一层更接近CPU读写速度的高速缓存(Cache),将运算使用到的数据复制到Cache中,让运算能加速进行,运算结束后再从Cache同步回内存之中。这个设计解决了速度的矛盾,也带来了一个新的问题:缓存一致性。在多CPU系统中,每个CPU都有自己的Cache,它们共享同一主内存,当多个CPU的运算任务涉及同一块内存区域时,就可能导致各自的Cache数据不一致。对此又设计了“缓存一致性协议”,如MESI,要求各个CPU在读写Cache时,都遵循这些协议进行操作,以解决缓存数据不一致的问题。“内存模型”(Memory Model),就是在特定的协议下,对特定的高速缓存读写访问过程进行抽象。不同架构的物理机器拥有不一样的内存模式,而Java虚拟机也有自己的内存模型,其基础原理是共通的。

  此外,为了充分利用CPU的运算单元,可能会对输入代码进行乱序执行优化,只保证执行结果的一致性,但不保证各语句的计算顺序与输入代码一致。Java虚拟机的即时编译器也有类似的指令重排序优化。

  Java语言规范中试图定义一种Java内存模型,以实现Java程序在各种平台上能达到一致的内存访问效果,为多线程的同步和避免数据争用提供一套有效平衡高吞吐与一致性的保障机制。

  什么是Java内存模型

  一个内存模型描述的是,给定程序的某个特定的执行轨迹(trace)是否是该程序的一个合法执行。Java内存模型检查执行轨迹中的每次读操作,以及根据特定规则,校验该读操作观察到的写是否合法。内存模型描述了一个程序的可预期行为,具体实现时拥有充分的自由度去生成需要的代码,只要其最终执行结果可经由内存模型进行推测。

  通俗地讲,Java内存模型(JMM)定义了一系列规则,以确保某一线程的写操作能正确呈现给其他线程。JMM并没有描述多线程该如何执行,而是描述多线程允许的行为。

  JMM规定了所有的共享变量都存储在JVM的主内存中。每条线程有自己的工作内存,用于保存该线程用到的变量的主内存副本拷贝(具体实现通常不会拷贝整个对象),线程对变量的操作全部在工作内存中进行,不能直接读写主内存中的变量。不同的线程间也无法直接访问对方的工作内存,线程间变量值的传递需要通过主内存来完成。

  关于主内存和工作内存之间的具体交互协议,即一个变量如何从主内存拷贝到工作内存、如何从工作内存同步回主内存之类的实现细节,JMM定义了8种操作(lock,unlock,read,load,use,assign,store,write),虚拟机实现时必须保证以上每一种操作都是原子的、不可再分的。

  共享变量/堆内存:能够在线程间共享的内存称作“共享内存或堆内存”。所有的实例域、静态域以及数组元素都存储在堆内存中。方法中的局部变量永远不会被线程间共享,也不会受内存模型影响。我们也无需关心线程内动作,每个单线程都应遵守正确的线程内语义。

  线程间的动作:线程间的动作是由某一线程执行,能被另一线程探测或直接影响的动作。包括:

  共享变量的读/写

  同步动作 (synchronization action)

  lock/unlock某个monitor;

  读写某个volatile变量

  启动一个线程

  与外部交互的动作

  导致某个线程进入无限循环的动作(thread devergence action)

  延伸阅读

  本文参考了《深入理解Java虚拟机》、《JSR-133-MemoryModel》,有充裕时间的同学可以去完整过一遍,但原文有较多艰涩难懂之处。这里做了较大的裁剪,隐藏更深一层的信息,以求对Java内存模型能有一个快速又不过于浅显的了解。更多的概念和规则:

  缓存一致性,Cache Coherence,MESI协议

  Instruction Reorder,指令重排序

  Happens-Before关系规则

  As-If-Serial ,线程内串行的语义

  Memory Barrier,内存屏障

  参考资料:

  JSR-133 Java Memory Model

  《Java语言规范SE8》第17章 线程与锁 17.4 内存模型

  《深入理解Java虚拟机》第12章 Java内存模型与线程

​

转载于:https://juejin.im/post/5bebcf1ff265da610e7fa454

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101323.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • Java 网络编程

    Java 网络编程

    2021年10月7日
  • CTS测试介绍(面试怎么介绍接口测试)

    CTS测试基本介绍CTS测试全称为系列兼容测试(CompatibilityTestsuite),CTS是为了测试手机是否符合google定义的兼容性规范(CompatibilityDefinition)。从而基于Android的应用程序能在基于同一个api版本的设备上面运行。通过CTS测试的设备可以获得Android的商标,并且享受AndroidMarket的权限。CTS测试是一个基于…

    2022年4月10日
  • 【零基础】MT4量化入门一:跑一个简单的boll

    【零基础】MT4量化入门一:跑一个简单的boll一、前言  今天开始研究MT4了,MT4是大大有名的外汇交易和量化软件,使用一种叫做MQL的语言来开发量化程序(跟C比较像)。因为是外国人做的,用的也大部分是外国人,使用起来不是很顺手,跟极星各有优劣吧。这里我就先逐步讲一下MT4的使用,然后再简单跑一个boll指标,最后汇总下使用心得。二、安装  1、下载MT4  不熟悉这东西,连安装都是个麻烦事儿。MT4官网好找一搜就有,下载链…

    2022年5月23日
  • 阿里云服务器开放端口如何设置_阿里云服务器8888端口

    阿里云服务器开放端口如何设置_阿里云服务器8888端口阿里云服务器开放端口阿里云服务器默认是只开放了部分端口,我们部署自己的服务需要监听一下80,8080等端口时,就需要自己设置安全策略,本文介绍如何设置阿里云的安全组,开放需要的端口步骤点击阿里云的的控制台点击进入云服务器点击进入安全组菜单,点击创建安全组按钮,添加一个新的安全组2.进入创建新安全组页面填写一下必要的信息,然后配置访问规则,包括入站和出站,点击手动添加一条,设置开放所有的端口,包括端口和授权对象,点击创建安全组按钮,将创建一条新的安全组出站我们也可以配置,默

    2022年10月3日
  • 单调队列java_单调队列&单调栈

    单调队列java_单调队列&单调栈单调队列例题:Poj2823给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数。数列长度:N<=106,m<=N对于单调队列,我们这样子来定义:1、维护区间最值2、去除冗杂状态如上题,区间中的两个元素a[i],a[j](假设现在再求最大值)若j>i且a[j]>=a[i],a[j]比a[i]还大而且还在后面(目前a[j]留在队列肯定比a[i]有用,因为你…

    2022年6月25日
  • CMD查看端口占用情况,8080端口被TIM占用了「建议收藏」

    CMD查看端口占用情况,8080端口被TIM占用了「建议收藏」CMD查看端口占用情况,8080端口被TIM占用了安装新版本dubboAdmin的时候,启动后端项目dubbo-admin-server报一下错误:org.apache.catalina.LifecycleException:Protocolhandlerstartfailed atorg.apache.catalina.connector.Connector.startInternal(Connector.java:1008) atorg.apache.catalina.util.Li

    2022年5月19日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号