Java并发编程之验证volatile指令重排-理论篇
Java并发编程之验证volatile指令重排-理论篇
Java并发包下的类中大量使用了volatile关键字。通过之前文章介绍,大家已经知道了volatile的三大特性:共享变量可见性;不保证原子性;禁止指令重排后顺序性。通过前面两篇文章我们通过代码验证了前两个特性,本文我们就来验证禁止指令重排保证顺序性。
指令重排序的生活例子
去餐厅吃饭预定位置的的时候。假设要去A餐厅吃饭,A餐厅有前台B、服务员C以及老板D。如果就只有你一个人去吃饭的时候,你给前台或者给服务器或者给老板说一声把2号桌预定了,半小时后过来。餐厅在为了2小时内就你一个人去吃饭。那么OK,没问题,别说等半个小时,就是等一个小时,2号桌还是你的。
但是,如果现在是吃饭高峰期,很多人来吃饭,你给前台说了,前台忙着没有及时给服务员或者没有给老板说,这个时候有个路人甲来吃饭,刚好看到2号桌没人,老板或者服务员就让他就坐2号桌吃饭了。那么,等你过来的时候,2号桌已经有人了。这个时候对于你来说,这个结果就不是你想要的了。
上面案例,如果从计算机执行指令角度来分析的话,你要到2号桌吃饭,这是预期结果。餐厅A就相当于是处理器,前台B就相当于是编译器,服务员C和老板D就是指令和内存系统。如果你预定的时间点不是吃饭高峰期或者没有人去餐厅A吃饭。那么你就相当于是一个线程。就是单线程的。老板、前台、服务员怎么安排都可以。因为只有你一个2号桌肯定是你的。这是单线程情况下。预期结果与实际结果就是一致的。
如果你预定的时间点是吃饭高峰期,很多人来吃饭(很多线程),这个时候为了餐厅效益,无论是前台还是服务员或者是老板都会对你的位置进行重排序。在你没有来的时候,会安排其他人到你预定的位置吃饭。如果其他人在你的位置吃饭,这个时候你再来吃饭,那么实际结果和预期结果就不一样了。这个时候餐厅应该做出相应的赔偿。为了解决这种赔偿问题,老板就想到了一个方案。做个牌子放在客人预定的桌子上。
当前台或者是服务员或者是老板看到餐桌上放的这个牌子,就知道这个位置不能再调动了。其中这个放在餐桌上的牌子就是特殊类型的内存屏障了。
示意图如下:
再来举个更常见的例子:
考试,在考试的时候老师会告诉我们,先做会做的,不会做的放到后面做。假设出题老师出题顺序是1-5,但是考试会根据自己实际情况做题顺序有可能是1、2、4、5、3或者是1、3、4、5、2等等。如果把出题老师看着是写代码的程序员,题目的顺序是代码一行一行的顺序,你的老师会告诉你先做会做的,此时老师就相当于是编译器,会排序一次。然后你自己做的时候又会进行重新排序,你自己就相当于是处理器又排序了一次。
上面两个现实生活中的案例,我们弄明白后,再来看看在计算机中指令重排问题,就很容易理解了。
指令重排
我们程序员编写的代码在JVM执行的时候,为了提高性能,编译器和处理器都会对代码编译后的指令进行重排序。分为3种:
1:编译器优化重排:
编译器的优化前提是在保证不改变单线程语义的情况下,对重新安排语句的执行顺序。
2:指令并行重排:
如果代码中某些语句之间不存在数据依赖,处理器可以改变语句对应机器指令的顺序
如:int x = 10;int y = 5;对于这种x y之间没有数据依赖关系的,机器指令就会进行重新排序。但是对于:int x = 10; int y = 5; int z = x+y;这种的,因为z和x y之间存在数据依赖(z=x+y)关系。在这种情况下,机器指令就不会把z排序在xy前面。
3:内存系统的重排序
通过之前的学习,我们知道了处理器和主内存之间还存在一二三级缓存。这些读写缓存的存在,使得程序的加载和存取操作,可能是乱序无章的。
指令重排序的流程图
通过上面介绍,我们可以知道从程序员写的Java源码到处理器真正实际执行的指令序列,会经历如下图的过程:
执行顺序:
源码编译器优化重排序(第一次排序) 指令重排序(第二次)内存重排序(第三次) 最终指向的指令。
无论是第一次编译器的重排序还是第二、三次的处理器重排序。这些重排序当在多线程的场景下可能会出现线程可见性的问题。
如在多线程的情况下,单例模式就不安全了。
为了解决这个问题,JMM允许编译器在生成指令顺序的时候,可以插入特定类型的内存屏障来禁止指令重排序。
当一个变量使用volatile修饰的时候,volatile关键字就是内存屏障。当编译器在生成指令顺序的时候,发现了volatile,就直接忽略掉。不再重排序了。
示意图:
证明volatile禁止指令重排演示代码,欢迎继续学习下一篇文章
欢迎关注凯哥公众号:凯哥Java(kaigejava)

Java并发编程之验证volatile指令重排-理论篇的更多相关文章
- Java并发编程之验证volatile不能保证原子性
Java并发编程之验证volatile不能保证原子性 通过系列文章的学习,凯哥已经介绍了volatile的三大特性.1:保证可见性 2:不保证原子性 3:保证顺序.那么怎么来验证可见性呢?本文凯哥(凯 ...
- Java并发编程之三:volatile关键字解析 转载
目录: <Java并发编程之三:volatile关键字解析 转载> <Synchronized之一:基本使用> volatile这个关键字可能很多朋友都听说过,或许也都用过 ...
- Java并发编程基础之volatile
首先简单介绍一下volatile的应用,volatile作为Java多线程中轻量级的同步措施,保证了多线程环境中“共享变量”的可见性.这里的可见性简单而言可以理解为当一个线程修改了一个共享变量的时候, ...
- Java并发编程学习:volatile关键字解析
转载:https://www.cnblogs.com/dolphin0520/p/3920373.html 写的非常棒,好东西要分享一下 Java并发编程:volatile关键字解析 volatile ...
- 干货:Java并发编程系列之volatile(二)
接上一篇<Java并发编程系列之synchronized(一)>,这是第二篇,说的是关于并发编程的volatile元素. Java语言规范第三版中对volatile的定义如下:Java编程 ...
- Java并发编程知识点总结Volatile、Synchronized、Lock实现原理
Volatile关键字及其实现原理 在多线程并发编程中,Volatile可以理解为轻量级的Synchronized,用volatile关键字声明的变量,叫做共享变量,其保证了变量的“可见性”以及“有序 ...
- Java并发编程里的volatile。Java内存模型核CPU内存架构的对应关系
CPU内存架构:https://www.jianshu.com/p/3d1eb589b48e Java内存模型:https://www.jianshu.com/p/27a9003c33f4 多线程下的 ...
- 【Java并发编程】:volatile变量修饰符
volatile用处说明 在JDK1.2之前,java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程环境下volatile关键 ...
- Java并发编程(二):volatile关键字
volatile是Java虚拟机提供的轻量级的同步机制.volatile关键字有如下两个作用,一句话概括就是内存可见性和禁止重排序. 1)保证被volatile修饰的共享变量对所有线程总是可见的,也就 ...
- 【转】关于Java并发编程的总结和思考
一.前言 就是想学习Java并发编程了,所以转载一下这篇认为还不错的博客~ 二.正文 编写优质的并发代码是一件难度极高的事情.Java语言从第一版本开始内置了对多线程的支持,这一点在当年是非常了不起的 ...
随机推荐
- vue大型电商项目尚品汇(前台篇)day03
堆积了两天一起发的,先祝大家节日快乐 后面任务很繁重,还有登录注册组件还有后台管理页面,真的繁重,我现在感觉每天全天时间都在学都不一定学得完,主要想在六月一号之前把整个项目过一遍.看看能不能创造奇迹 ...
- 钉钉应用开发-Python操作钉钉文档(excel版)
钉钉应用开发-Python操作钉钉文档 一: 服务端SDK下载 服务端SDK下载 - 钉钉开放平台 (dingtalk.com) pip3 install alibabacloud_dingtalk ...
- 树莓派4B-控制直流电机
树莓派4B-控制直流电机 一.硬件介绍 树莓派 L298N电机驱动模块 直流电机 外接电源 杜邦线 二.硬件连接 原理图: 注意:ENA和ENB的跳冒必须安上去,如果没有拿杜邦线连通! 三.代码编写 ...
- Idea 2020.1 编译SpringBoot项目Kotlin报错
导读 今天公司有个项目莫名其妙的运行不起来,提示Kotlin版本兼容问题,网上找到解决方案后,整理下来. 错误信息 Error:Kotlin: Module was compiled with an ...
- linux 查看端口状态
查看端口 netstat -tlun 查看端口被那个服务占用 netstat -tunlp |grep 8080
- 女朋友问我 LB 是谁?
科普一下 LB(负载均衡)技术 我的编程导航网站:www.code-nav.cn 大家好,我是鱼皮. 周末在家写代码,无意中跟女朋友提了下 LB,还说 LB 好的呱呱叫. 她笑了笑,问我 LB 是谁? ...
- [oeasy]python0012_字符_character_chr函数_根据序号得到字符
字符(character) 回忆上次内容 上次了解了ord函数 这个函数可以通过字符得到序号 那么可以反过来吗? 通过序号得到字符可以吗? 编辑 ord的逆运算chr 有来就有回 编辑 好 ...
- lvs的nat和dr模式混合用
机器部署信息 lvs : 10.0.0.200 vip 10.0.0.19 外网IP , 172.168.1.19 内网IP dr rs: 10.0.0.200 vip 10.0.0.18 rip ...
- 靶机: AdmX_new
靶机: AdmX_new 准备阶段 靶机:https://download.vulnhub.com/admx/AdmX_new.7z 下载后进行 MD5:2948034da23a8acc1285fd4 ...
- 「图论」Bron-kerbosch算法
7.21晚上加赛 T2.七负我,做这题找到了性质发现需要求最大团,不会,爆搜,打假了,赛后改,对了,但时间复杂度大爆炸,看下发题解,有这么一句话:于是学习了一下. Bron-kerbosch算法-求图 ...