处理器内存模型

顺序一致性内存模型是一个理论参考模型,JMM 和处理器内存模型在设计时通常会把顺序一致性内存模型作为参照。JMM 和处理器内存模型在设计时会对顺序一致性模型做一些放松,因为如果完全按照顺序一致性模型来实现处理器和 JMM,那么很多的处理器和编译器优化都要被禁止,这对执行性能将会有很大的影响。

根据对不同类型读/写操作组合的执行顺序的放松,可以把常见处理器的内存模型划分为下面几种类型:

  1. 放松程序中写-读操作的顺序,由此产生了 total store ordering 内存模型(简称为TSO)。
  2. 在前面1的基础上,继续放松程序中写-写操作的顺序,由此产生了 partial store order 内存模型(简称为 PSO)。
  3. 在前面1和2的基础上,继续放松程序中读-写和读-读操作的顺序,由此产生了 relaxed memory order 内存模型(简称为 RMO)和 PowerPC 内存模型。

注意,这里处理器对读/写操作的放松,是以两个操作之间不存在数据依赖性为前提的(因为处理器要遵守 as-if-serial 语义,处理器不会对存在数据依赖性的两个内存操作做重排序)。

下面的表格展示了常见处理器内存模型的细节特征:

内存模型名称 对应的处理器 Store-Load 重排序 Store-Store重排序 Load-Load 和Load-Store重排序 可以更早读取到其它处理器的写 可以更早读取到当前处理器的写
TSO sparc-TSOX64 Y       Y
PSO sparc-PSO Y Y     Y
RMO ia64 Y Y Y   Y
PowerPC PowerPC Y Y Y Y Y

在这个表格中,我们可以看到所有处理器内存模型都允许写-读重排序,原因在第一章以说明过:它们都使用了写缓存区,写缓存区可能导致写-读操作重排序。同时,我们可以看到这些处理器内存模型都允许更早读到当前处理器的写,原因同样是因为写缓存区:由于写缓存区仅对当前处理器可见,这个特性导致当前处理器可以比其他处理器先看到临时保存在自己的写缓存区中的写。

上面表格中的各种处理器内存模型,从上到下,模型由强变弱。越是追求性能的处理器,内存模型设计的会越弱。因为这些处理器希望内存模型对它们的束缚越少越好,这样它们就可以做尽可能多的优化来提高性能。

由于常见的处理器内存模型比 JMM 要弱,java 编译器在生成字节码时,会在执行指令序列的适当位置插入内存屏障来限制处理器的重排序。同时,由于各种处理器内存模型的强弱并不相同,为了在不同的处理器平台向程序员展示一个一致的内存模型,JMM 在不同的处理器中需要插入的内存屏障的数量和种类也不相同。下图展示了 JMM 在不同处理器内存模型中需要插入的内存屏障的示意图:

如上图所示,JMM 屏蔽了不同处理器内存模型的差异,它在不同的处理器平台之上为 java 程序员呈现了一个一致的内存模型。

JMM,处理器内存模型与顺序一致性内存模型之间的关系

JMM 是一个语言级的内存模型,处理器内存模型是硬件级的内存模型,顺序一致性内存模型是一个理论参考模型。下面是语言内存模型,处理器内存模型和顺序一致性内存模型的强弱对比示意图:

从上图我们可以看出:常见的4种处理器内存模型比常用的3中语言内存模型要弱,处理器内存模型和语言内存模型都比顺序一致性内存模型要弱。同处理器内存模型一样,越是追求执行性能的语言,内存模型设计的会越弱。

JMM 的设计

从 JMM 设计者的角度来说,在设计 JMM 时,需要考虑两个关键因素:

  • 程序员对内存模型的使用。程序员希望内存模型易于理解,易于编程。程序员希望基于一个强内存模型来编写代码。
  • 编译器和处理器对内存模型的实现。编译器和处理器希望内存模型对它们的束缚越少越好,这样它们就可以做尽可能多的优化来提高性能。编译器和处理器希望实现一个弱内存模型。

由于这两个因素互相矛盾,所以 JSR-133 专家组在设计 JMM 时的核心目标就是找到一个好的平衡点:一方面要为程序员提供足够强的内存可见性保证;另一方面,对编译器和处理器的限制要尽可能的放松。下面让我们看看 JSR-133 是如何实现这一目标的。

为了具体说明,请看前面提到过的计算圆面积的示例代码:

double pi  = 3.14;    //A
double r = 1.0; //B
double area = pi * r * r; //C

上面计算圆的面积的示例代码存在三个 happens- before 关系:

  1. A happens- before B;
  2. B happens- before C;
  3. A happens- before C;

由于 A happens- before B,happens- before 的定义会要求:A 操作执行的结果要对B可见,且 A 操作的执行顺序排在B操作之前。 但是从程序语义的角度来说,对A和B做重排序即不会改变程序的执行结果,也还能提高程序的执行性能(允许这种重排序减少了对编译器和处理器优化的束缚)。也就是说,上面这3个 happens- before 关系中,虽然2和3是必需要的,但1是不必要的。因此,JMM 把 happens- before 要求禁止的重排序分为了下面两类:

  • 会改变程序执行结果的重排序。
  • 不会改变程序执行结果的重排序。

JMM 对这两种不同性质的重排序,采取了不同的策略:

  • 对于会改变程序执行结果的重排序,JMM 要求编译器和处理器必须禁止这种重排序。
  • 对于不会改变程序执行结果的重排序,JMM 对编译器和处理器不作要求(JMM 允许这种重排序)。

下面是JMM的设计示意图:

从上图可以看出两点:

  • JMM 向程序员提供的 happens- before 规则能满足程序员的需求。JMM 的 happens- before 规则不但简单易懂,而且也向程序员提供了足够强的内存可见性保证(有些内存可见性保证其实并不一定真实存在,比如上面的 A happens- before B)。
  • JMM 对编译器和处理器的束缚已经尽可能的少。从上面的分析我们可以看出,JMM 其实是在遵循一个基本原则:只要不改变程序的执行结果(指的是单线程程序和正确同步的多线程程序),编译器和处理器怎么优化都行。比如,如果编译器经过细致的分析后,认定一个锁只会被单个线程访问,那么这个锁可以被消除。再比如,如果编译器经过细致的分析后,认定一个 volatile 变量仅仅只会被单个线程访问,那么编译器可以把这个 volatile 变量当作一个普通变量来对待。这些优化既不会改变程序的执行结果,又能提高程序的执行效率。

JMM 的内存可见性保证

Java 程序的内存可见性保证按程序类型可以分为下列三类:

  1. 单线程程序。单线程程序不会出现内存可见性问题。编译器,runtime 和处理器会共同确保单线程程序的执行结果与该程序在顺序一致性模型中的执行结果相同。
  2. 正确同步的多线程程序。正确同步的多线程程序的执行将具有顺序一致性(程序的执行结果与该程序在顺序一致性内存模型中的执行结果相同)。这是 JMM 关注的重点,JMM 通过限制编译器和处理器的重排序来为程序员提供内存可见性保证。
  3. 未同步/未正确同步的多线程程序。JMM 为它们提供了最小安全性保障:线程执行时读取到的值,要么是之前某个线程写入的值,要么是默认值(0,null,false)。

下图展示了这三类程序在 JMM 中与在顺序一致性内存模型中的执行结果的异同:

只要多线程程序是正确同步的,JMM 保证该程序在任意的处理器平台上的执行结果,与该程序在顺序一致性内存模型中的执行结果一致。

JSR-133 对旧内存模型的修补

JSR-133 对 JDK5 之前的旧内存模型的修补主要有两个:

  • 增强 volatile 的内存语义。旧内存模型允许 volatile 变量与普通变量重排序。JSR-133 严格限制 volatile 变量与普通变量的重排序,使 volatile 的写-读和锁的释放-获取具有相同的内存语义。
  • 增强 final 的内存语义。在旧内存模型中,多次读取同一个 final 变量的值可能会不相同。为此,JSR-133 为 final 增加了两个重排序规则。现在,final 具有了初始化安全性。

java内存模型-总结的更多相关文章

  1. JVM学习(3)——总结Java内存模型

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 为什么学习Java的内存模式 缓存一致性问题 什么是内存模型 JMM(Java Memory Model)简 ...

  2. 浅析java内存模型--JMM(Java Memory Model)

    在并发编程中,多个线程之间采取什么机制进行通信(信息交换),什么机制进行数据的同步? 在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的. 线程之间通过共享程序公共的状态,通 ...

  3. JMM(java内存模型)

    What is a memory model, anyway? In multiprocessorsystems, processors generally have one or more laye ...

  4. 《深入理解Java内存模型》读书总结

    概要 文章是<深入理解Java内容模型>读书笔记,该书总共包括了3部分的知识. 第1部分,基本概念 包括"并发.同步.主内存.本地内存.重排序.内存屏障.happens befo ...

  5. Java内存模型深度解析:final--转

    原文地址:http://www.codeceo.com/article/java-memory-6.html 与前面介绍的锁和Volatile相比较,对final域的读和写更像是普通的变量访问.对于f ...

  6. Java内存模型深度解析:volatile--转

    原文地址:http://www.codeceo.com/article/java-memory-4.html Volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特 ...

  7. Java内存模型深度解析:顺序一致性--转

    原文地址:http://www.codeceo.com/article/java-memory-3.html 数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争.java内存模型规范对数据 ...

  8. Java内存模型深度解析:基础部分--转

    原文地址:http://www.codeceo.com/article/java-memory-1.html 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何 ...

  9. 深入理解java内存模型系列文章

    转载关于java内存模型的系列文章,写的非常好. 深入理解java内存模型(一)--基础 深入理解java内存模型(二)--重排序 深入理解java内存模型(三)--顺序一致性 深入理解java内存模 ...

  10. Java内存模型深度解读

    Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的.Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型. 如果你想设计表现良好的并发 ...

随机推荐

  1. HTTP学习补充一

    1 HTTP协议协商 1.1 NPN NPN:Next Protocol Negotiation,是由Google公司开发的用于SPDY进行协议协商扩展. 协商过程: 服务端在收到客户端的client ...

  2. WEBAPP开发技巧(手机网站开发注意事项)

    以下只是我个人得总结,如果你有更好的建议,请留言,一起共勉进步!!- -! 1.要响应式开发web,也就是页面必须自适应屏幕大小,可以采用流体布局,如之前的文章(自适应宽度布局),其他具体的小问题可以 ...

  3. 基于Metronic的Bootstrap开发框架经验总结(7)--数据的导入、导出及附件的查看处理

    在很多系统模块里面,我们可能都需要进行一定的数据交换处理,也就是数据的导入或者导出操作,这样的批量处理能给系统用户更好的操作体验,也提高了用户录入数据的效率.我在较早时期的EasyUI的Web框架上, ...

  4. JavaScript获取图片的原始尺寸

    页面里的img元素,想要获取它的原始尺寸,以宽度为例可能首先想到的就是width,如下 <img src="http://img11.360buyimg.com/da/g14/M07/ ...

  5. mysql replication principle--转

    原文地址:http://www.codeweblog.com/mysql-replication-principle/ 1, the replication process Mysql replica ...

  6. 如何在windows 10 x64安装佳能 CP900 驱动

    佳能太无耻,为了销售CP910 , CP900 到win8 ,win8.1,win 10 都没有驱动程序,网上找的方法都不行,IT民工自有办法: 1.按住shift键,重启电脑 restart 2.在 ...

  7. RHEL6 某业务用户ulimit -a命令找不到

    最终确定是shell环境问题,临时改为/bin/bash即可查看. 1.问题现象 # su - jingyu $ id uid=(jingyu) gid=(jingyu) (jingyu) $ uli ...

  8. 赞!15个来自 CodePen 的酷炫 CSS 动画效果

    CodePen 是一个在线的前端代码编辑和展示网站,能够编写代码并即时预览效果.你在上面可以在线分享自己的 Web 作品,也可以欣赏到世界各地的优秀开发者在网页中实现的各种令人惊奇的效果. 今天这篇文 ...

  9. HTML5本地存储 Web Storage

    Web Storage基本介绍 HTML5 定义了本地存储规范 Web Storage , 提供了两种存储类型 API  sessionStorage 和 localStorage,二者的差异主要是数 ...

  10. [New Portal]Windows Azure Virtual Machine (21) 将本地Hyper-V的VM上传至Windows Azure Virtual Machine

    <Windows Azure Platform 系列文章目录> 本章介绍的内容是将本地Hyper-V的VHD,上传到Azure数据中心,并且保留OS中的内容. 注意:笔者没有执行Syspr ...