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)
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
【免费百度网盘不限速】爱奇艺万能联播 百度网盘不限速的方法
大家都知道其实爱奇艺和某度就是一家的,最新的万能联播版本,加入了很多功能,感觉很不错。最最最主要是支持百度云不限速下载,百度网盘干什么用的就不用多解释了。资源确实丰富,但是难免有时候要下载一些文件资料,尤其是比较大的文件,百度网盘客户端的下载速度可真是不咋地。。你当然可以选择充值百度超级会员,不过凯哥想说的是,其实还是有其他的方法,能够突破限制,通过第三方下载软件,实现高速下载。 百度网盘文件免费高速下载的方法,这次咱们利用一个百度官方方法的例子来解决这个问题,分享给大家,于是就有了今天这篇文章。 准备要素 百度网盘账号(被官方拉黑就不行喽) 爱奇艺万能联播 操作方法 下载的是爱奇艺万能联播!爱奇艺万能联播!!爱奇艺万能联播!!!重要事情说三遍。不是爱奇艺播放器。再说一次,不是爱奇艺播放器。爱奇艺播放器不能的。 1. 打开爱奇艺万能联播,点击访问网盘,如下图所示。 利用爱奇艺万能联播免费高速下载百度网盘文件或者在线播放网速杠杠滴~~ 2. 根据提示输入自己的百度网盘账号,登录后点击下载文件。 来测试测试在线播放效果,直接点击在线播放: 再来测试测试下载速度: 利用爱奇艺万能联播免费高速...
- 下一篇
阿里云视觉智能平台高校学生专访|臧家河:疫情在家,我的视觉AI实践之旅
因新冠肺炎疫情,学校延期开学。为了让广大学生在家时间不浪费,提高相关计算机技能。阿里云多方产品联合开发者社区,推出了高校“在家实践”计划,其中阿里云视觉智能开放平台(vision.aliyun.com)为赋能此次活动,助力大学生提高技能,所有参加此次活动的高校学生均可免费使用该平台下的70+种视觉AI能力,另外参加此次活动每人还可免费领取一台云服务器ECS以及在线实践课程等资源。 在活动举办期间,很多同学通过现有的资源搭建出了属于自己的网站或者是博客,并对接相关功能,成功实现网页功能的配置。我们有幸采访到了其中一位开发者臧家河同学,那么接下来听听他是怎么看待此次活动的。 案例地址:http://ms.bcaqfy.xin/AliAi/ 阿里云:加入此次活动的初衷是什么?臧家河:本身作为一个软件技术专业的学生来说,本身就对科技类开发类的知识感兴趣,当时也是抱着提高自身技术、开拓视野结交更多的开发牛人的想法,因此报名参加了此次活动。 阿里云:是什么原因让你制作了车牌识别页面呢?臧家河:在报名此次活动后有加入对应的钉钉群,在群里面发现很多技术大牛在分享自己的作品,这也促使我萌生出制...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS关闭SELinux安全模块
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程