关于重排序

重排序通常是编译器或运行时环境为了优化程序性能而采取的对指令进行重新排序执行的一种手段。

重排序分为两类:编译期重排序和运行期重排序,分别对应编译时和运行时环境。

As-if-serial语义

as-if-serial语义的意思是,所有的动作(Action)都可以为了优化而被重排序,但是必须保证它们重排序后的结果和程序代码本身的应有结果是一致的。

Java编译器、运行时和处理器都会保证单线程下的as-if-serial语义。

比如,为了保证这一语义,重排序不会发生在有数据依赖的操作之中。

int a = 1;
int b = 2;
int c = a + b;

将上面的代码编译成Java字节码或生成机器指令,可视为展开成了以下几步动作(实际可能会省略或添加某些步骤)。

对a赋值1
对b赋值2
取a的值
取b的值
将取到两个值相加后存入c

在上面5个动作中,动作1可能会和动作2、4重排序,动作2可能会和动作1、3重排序,动作3可能会和动作2、4重排序,动作4可能会和1、3重排序。但动作1和动作3、5不能重排序。动作2和动作4、5不能重排序。因为它们之间存在数据依赖关系,一旦重排,as-if-serial语义便无法保证。

内存屏障

内存屏障(Memory Barrier,或叫做内存栅栏,Memory Fence)是一组处理器指令,用于实现对内存操作的顺序限制,控制特定条件下的重排序和内存可见性问题。Java编译器会根据内存屏障的规则禁止重排序。

内存屏障可以被分为以下几种类型
LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。

有的处理器的重排序规则较严,无需内存屏障也能很好的工作,Java编译器会在这种情况下不放置内存屏障。
为了实现上一章中讨论的JSR-133的规定,Java编译器会这样使用内存屏障。

内容来自美团网技术博客

好文书签

Java内存访问重排序的研究

深入理解Java内存模型(二)——重排序

内存屏障与JVM并发

理解重排序

Java内存访问重排序笔记的更多相关文章

  1. java内存模型——重排序

    线程安全问题概括来说表现为三个方面:原子性,可见性和有序性. 在多核处理器的环境下:编译器可能改变两个操作的先后顺序:处理器可能不是完全依照程序的目标代码所指定的顺序执行命令:一个处理器执行的多个操作 ...

  2. java内存模型-重排序

    数据依赖性 如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性.数据依赖分下列三种类型: 名称 代码示例 说明 写后读 a = 1;b = a; 写一个变量之 ...

  3. java高并发核心要点|系列4|CPU内存指令重排序(Memory Reordering)

    今天,我们来学习另一个重要的概念. CPU内存指令重排序(Memory Reordering) 什么叫重排序? 重排序的背景 我们知道现代CPU的主频越来越高,与cache的交互次数也越来越多.当CP ...

  4. 《深入理解 Java 内存模型》读书笔记

    ![img](https://mmbiz.qpic.cn/mmbiz_jpg/1flHOHZw6RtPu3BNx3zps1JhSmPICRw7QgeOmxOfTbCT3RLgIo4qRpn6xL4qg ...

  5. 转《深入理解 Java 内存模型》读书笔记

    转:https://mp.weixin.qq.com/s/2hA6u4hLEPWlTPdD-XB-bg 前提 <深入理解 Java 内存模型>程晓明著,该书在以前看过一遍,现在学的东西越多 ...

  6. java基础之 重排序

    重排序通常是编译器或运行时环境为了优化程序性能而采取的对指令进行重新排序执行的一种手段.重排序分为两类:编译期重排序和运行期重排序,分别对应编译时和运行时环境. 在并发程序中,程序员会特别关注不同进程 ...

  7. java内存知识点扩展_笔记

    一.java的虚拟机分为三大区域: 执行引擎, java运行内存, 类加载器 1.1.Java运行内存分为线程共享区域和线程私有区: 我们大多数初学者用的都是sun公司最早设计的Java HotSpo ...

  8. Java并发编程原理与实战四十一:重排序 和 happens-before

    一.概念理解 首先我们先来了解一下什么是重排序:重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段. 从Java源代码到最终实际执行的指令序列,会分别经历下面3种重排序,如下图 ...

  9. 13 Java内存模型

    数据竞争 int a=0, b=0; public void method1() { int r2 = a; b = 1; } public void method2() { int r1 = b; ...

随机推荐

  1. 嵌入式实时操作系统μCOS原理与实践+事件部分代码

    //事件等待表的初始化函数:pevent表示事件控制块的指针#if (OS_EVENT_EN)void  OS_EventWaitListInit (OS_EVENT *pevent){    INT ...

  2. redis安装步骤

    7.1创建业务安装用户 安装和配置Redis软件时,需要使用redis用户登录服务器进行相关操作,因此需要创建redis的业务安装用户组和redis的业务安装用户.此操作在主备机上同时进行. 创建用户 ...

  3. jQuery操作滚动条

    一.窗体滚动条 1.获取窗体滚动条当前纵向和横向位置 var currentY=$(document.body).scrollTop();//窗体滚动条纵向位置 var currentX=$(docu ...

  4. linux source与 . 命令

    source命令用法:source FileName作用:在当前bash环境下读取并执行FileName中的命令.注:该命令通常用命令“.”来替代.如:source .bash_rc 与 . .bas ...

  5. Linux下不同机器之间的文件拷贝

    通过 scp 命令实现不同机器之间的文件拷贝. (1)本机考到目标机器:scp 本机文件 目的地: 如:scp /home/odp-web.war   root@192.168.6.137:/usr/ ...

  6. phpcms 采集教程

    Phpcms网站管理系统目前最新版本为Phpcms v9,作为国内主流CMS系统之一,目前已有数万网站的应用规模.那么其自带的采集模块功能如何呢,来看看吧. 文章采集 Phpcms v9默认内置有文章 ...

  7. mono 3.4.0 make install的时候出现"找不到 Microsoft.Portable.Common.targets 文件”的错误提示解决方法

    如果在这时就进行配置安装Mono的话,会在make阶段得到一个“找不到 Microsoft.Portable.Common.targets 文件”的错误提示, 所以需要先进行如下处理: #> c ...

  8. (转)DoDataExchange执行时机

    void CRegisterDialog::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DAT ...

  9. 使用node.js制作简易爬虫

    最近看了些node.js方面的知识,就像拿它来做些什么.因为自己喜欢摄影,经常上蜂鸟网,所以寻思了一下,干脆做个简单的爬虫来扒论坛的帖子. 直接上代码吧. var sys = require(&quo ...

  10. Sublime Text2 快捷键 (MAC版)

    工具是人的延伸,可以把人变得更聪明更强大,人类正是学会了使用工具,才创造出现在的文明.作为程序员,工具开发.使用是其能力的重要体现,业内的大牛都是造工具的好手.目前身边很多人都在用sublime te ...