一、happns-before

  happns-before是学习指令重排序前的一个必须了解的知识点,他的作用主要是就是用来判断代码的执行顺序。

  1.定义

  happens-before是用来指定两个操作之间的执行顺序。提供跨线程的内存可见性。

  在java内存模型中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必然存在happens-before关系

  2.happens-before规则

  a.程序顺序规则

  单线程中的每个操作,总是前一个操作happens-before于该线程中的任意后续操作。

  简单的说,这个规则就是代码按照顺序执行。

  b.监视器规则

  对一个锁的解锁,总是happens-before于随后对这个锁的加锁。

  这句话可以理解成对于同一把锁,释放与获取是线程可见的;释放锁的操作总是happens-before于获取锁的操作。

  c.volatile变量规则

  对一个volatile域的写总是happens-before于任意后续对这个volatile域的读。

  就是说被volatile修饰的变量,在线程中是是可见的。

  d.传递性

  这个规则与程序性规则相识:有A、B、C三变量,如果根据程序性规则:

    A变量 happens-before B变量,

    B变量 happens-before C变量,

    则必然有

    A变量 happens-before C变量。

  f.start规则

  这个规则是在多线程场景中会经常出现的:A线程中调用了B线程,那么A线程happens-before于B线程。

  或者说A线程的结果对B线程是可见的(结果必须在调用B线程前就已经出现)。

  g.join规则

  多线程场景中,如果有线程使用了join方法,那么join的线程一点是happens-before于调用的线程。

二、指令重排序

  了解过happens-before后,终于可以进入本结的主题了指令重排序。

  1.定义

  我们知道jvm运行的是java文件编译后的字节码指令,编译器为了优化程序的性能,会重新对字节码指令排序,虽然会重排序,但是指令重排序运行的结果一定是正常的。

  2.数据的依赖性

  能够进行指令重排序的地方,就是看这个段代码的数据依赖性,有三种情况是不能够进行指令重排序的:

  ①对某个对象或者变量,先进行赋值再读这个对象的值(写后读)

  ②对某个对象或者变量,先读这个对象的值再对这个对象赋值(读后写)

  ③对某个对象或者变量,先后进行了两次赋值(写后写)

  如果对这三种情况进行指令重排序的话,获得的结果一定是错误的。所以规定在这三种情况中,是不能进行指令重排序。

  3.指令重排序所带来的影响

  指令重排序一共分为两种情况:

  a.编译器重排序

  b.处理器重排序(这个必须是在多个CPU情况下才会发生)

  指令重排序在单线程中对我们程序的帮助一定是正向的,它能够很好的优化我们程序的性能。但是在多线程情况下,就不一定了,但是出现指令重排序情况导致线程安全性问题的情况都是很少见的,就算出现也是很难去发现的。最简单的例子:双检查锁单例模式。如果出现了由于指令重排序造成的线程安全性问题,就可以使用volatile关键字来解决。

  

  

java并发学习--第九章 指令重排序的更多相关文章

  1. Java并发(三):重排序

    在执行程序时为了提高性能,提高并行度,编译器和处理器常常会对指令做重排序.重排序分三种类型: 编译器优化的重排序.编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序. 指令级并行的重排序 ...

  2. Java并发编程的艺术(二)——重排序

    当我们写一个单线程程序时,总以为计算机会一行行地运行代码,然而事实并非如此. 什么是重排序? 重排序指的是编译器.处理器在不改变程序执行结果的前提下,重新排列指令的执行顺序,以达到最佳的运行效率. 重 ...

  3. java并发学习--第一章 线程的创建

    所谓的并发就是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行.所以我们看似几个线程在同时进行,其实在操作系统中 ...

  4. java并发学习--第二章 spring boot实现线程的创建

    除了之前介绍的创建线程方式外,spring boot为我们了提供一套完整的线程创建方式,其中包括了:线程.线程池.线程的监控. 一.使用spring boot提供的方法创建线程与线程池 1.首先在sp ...

  5. Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  6. Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)

    一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...

  7. java指令重排序的问题

    转载自于:http://my.oschina.net/004/blog/222069?fromerr=ER2mp62C 指令重排序是个比较复杂.觉得有些不可思议的问题,同样是先以例子开头(建议大家跑下 ...

  8. JVM学习(八)指令重排序

    一.数据依赖性 在学习JVM的指令重排序之前,我们先了解一下什么是数据依赖性: 编译器和处理器在处理具体的指令时,可能会对操作进行重排序来提高执行性能[多条指令并行执行,所以提升性能的同时也可能会导致 ...

  9. 不得不提的volatile及指令重排序(happen-before)

    微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...

随机推荐

  1. nodejs 文件操作

    前言: nodejs 自带的文件操作的模块  fs 就是对文件的增删查改: 就像我们用的服务器,我们没有办法在运行的文件上进行一直的修改,因为他不向浏览器,刷新后我们的文件会自己修改: 如果想要更改我 ...

  2. JNI写本地日志文件

    调试JNI库 我喜欢反编译APK 然后替换.so文件 然后再编译成APK 其中写日志的话 用fopen("/sdcard/lei.txt","wb+")

  3. 【重点突破】—— UniApp微信小程序开发教程学习Three

    一.实战 HBuilderX:在微信小程序中运行页面,需要设置->安全 开启微信小程序服务端口,HBuilder工具->设置->配置程序路径 网络请求.模板语法.打开页面.页面传参 ...

  4. Linux高级调试与优化——gdb调试命令

    番外 2019年7月26日至27日,公司邀请<软件调试>和<格蠹汇编——软件调试案例集锦>两本书的作者张银奎老师进行<Linux高级调试与优化>培训,有幸聆听张老师 ...

  5. WPF 绑定数据方式

    ======================================================================== Foreground="{Binding P ...

  6. python学习中

    python中的单引号.双引号.三引号的用法 网上也查找了资料,理解的都有些费劲 就自己验证了一下(主要是目前掌握的python知识,不知道什么时候会同时用到这三种引号) 用python3验证的 单引 ...

  7. hadoop 2.5.2源码编译

    编译过程漫长无比,错误百出,需要耐心耐心!! 1.准备的环境及软件 操作系统:Centos6.4 64位 jdk:jdk-7u80-linux-x64.rpm,不要使用1.8 maven:apache ...

  8. 【Linux开发】IO streaming DMA buffer importing

    http://linuxtv.org/downloads/v4l-dvb-apis/dmabuf.html I/O流 (DMA缓存引用) 这是一个实验性接口,将来可能发生改变 DMABUF框架提供了在 ...

  9. 如何有效的使用google进行搜索的20个技能

    每天有数百万人因为各种各样的原因使用谷歌搜索.学生们把它用于学校,商人们把它用于研究,还有数百万人把它用于娱乐.但大多数人可能没有充分利用谷歌搜索的潜力. 想要更有效地使用谷歌搜索,并得到您想要的搜索 ...

  10. [Web 前端] 034 计算属性,侦听属性

    目录 0. 方便起见,定个轮廓 1. 过滤器 2. 计算属性 2.1 2.2 3. 监听属性 0. 方便起见,定个轮廓 不妨记下方的程序为 code1 <!DOCTYPE html> &l ...