java并发学习--第九章 指令重排序
一、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并发学习--第九章 指令重排序的更多相关文章
- Java并发(三):重排序
在执行程序时为了提高性能,提高并行度,编译器和处理器常常会对指令做重排序.重排序分三种类型: 编译器优化的重排序.编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序. 指令级并行的重排序 ...
- Java并发编程的艺术(二)——重排序
当我们写一个单线程程序时,总以为计算机会一行行地运行代码,然而事实并非如此. 什么是重排序? 重排序指的是编译器.处理器在不改变程序执行结果的前提下,重新排列指令的执行顺序,以达到最佳的运行效率. 重 ...
- java并发学习--第一章 线程的创建
所谓的并发就是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行.所以我们看似几个线程在同时进行,其实在操作系统中 ...
- java并发学习--第二章 spring boot实现线程的创建
除了之前介绍的创建线程方式外,spring boot为我们了提供一套完整的线程创建方式,其中包括了:线程.线程池.线程的监控. 一.使用spring boot提供的方法创建线程与线程池 1.首先在sp ...
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- Java的多线程机制系列:(四)不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- java指令重排序的问题
转载自于:http://my.oschina.net/004/blog/222069?fromerr=ER2mp62C 指令重排序是个比较复杂.觉得有些不可思议的问题,同样是先以例子开头(建议大家跑下 ...
- JVM学习(八)指令重排序
一.数据依赖性 在学习JVM的指令重排序之前,我们先了解一下什么是数据依赖性: 编译器和处理器在处理具体的指令时,可能会对操作进行重排序来提高执行性能[多条指令并行执行,所以提升性能的同时也可能会导致 ...
- 不得不提的volatile及指令重排序(happen-before)
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
随机推荐
- React Native商城项目实战05 - 设置首页的导航条
1.Home.js /** * 首页 */ import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Te ...
- maven 成长之路
1配置maven 环境变量 新建系统变量 M2_HOME :E:\apache-maven-3.5.2 在系统变量 path中添加 E:\apache-maven-3.5.2\bin 运行 mvn - ...
- maven之阿里云Maven镜像的使用
Maven中央仓库在国外,速度比较慢,所以我们采用国内的镜像,速度回有质的提升. 配置下setting.xml <mirrors> <mirror> <id>ali ...
- 无法加载程序集XXX.dll 此程序集可能是从 Web 上下载的
错误 13 无法加载程序集 file:///D:\Documents\Downloads\kaxaml-master\kaxaml-master\packages\Prism.4.0.0. ...
- docker常用软件安装及使用
linux安装docker: sudo wget -qO- https://get.docker.com | sh 启动docker: service docker start 搜索镜像: docke ...
- Maven使用WEB-INF/lib下面的jar编译和打包
在某些情况下,maven无法下载依赖的jar,或者依赖的m2会非常的大,上G那是随随便便的事.为了方便修改和编译,在打出的war包基础上,或者直接把tomcat的webapps下的项目拿出来,就可以用 ...
- 【web前端】面题整理(2)
今天是520,单身狗在这里祝各位520快乐! DOM节点统计 DOM 的体积过大会影响页面性能,假如你想在用户关闭页面时统计(计算并反馈给服务器)当前页面中元素节点的数量总和.元素节点的最大嵌套深度以 ...
- 2019暑假第三周(HDFS和HBase)
Hadoop的核心是HDFS和MapReduce. 1.分布式文件系统HDFS理论方面的认知学习. 2.HDFS编程实践. 3.分布式数据库HBase.
- 【Python】关于近期爬虫学习的总结
写在开头 在之前的三篇文章中,我尝试了使用python爬虫实现的对于特定站点的<剑来>小说的爬取,对于豆瓣的短评的爬取,也有对于爬取的短评数据进行的词云展示,期间运用了不少的知识,现在是时 ...
- jenkins自动化测试Email Extension邮件模板 及可用参数TEST_COUNTS ,FAILED_TESTS详细说明
先列出模板内容: <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <t ...