JVM系列之:从汇编角度分析Volatile
发布时间:2023-11-26 14:33:46
Volatile关键字对熟悉java多线程的朋友来说,应该很熟悉了。Volatile是JMM(Java Memory Model)的一个非常重要的关键词。通过是用Volatile可以实现禁止重排序和变量值线程之间可见两个主要特性。今天我们从汇编的角度来分析一下Volatile关键字到底是怎么工作的。
重排序
这个世界上有两种重排序的方式。
第一种,是在编译器级别的,你写一个java源代码,经过javac编译之后,生成的字节码顺序可能跟源代码的顺序不一致。
第二种,是硬件或者CPU级别的重排序,为了充分利用多核CPU的性能,或者CPU自身的处理架构(比如cache line),可能会对代码进行重排序。比如同时加载两个非互相依赖的字段进行处理,从而提升处理速度。
我们举个例子:
public class TestVolatile { private static int int1; private static int int2; private static int int3; private static int int4; private static int int5; public static void mAIn(String[] args) throws InterruptedException { for (int i = ; i < 10000; i++) { increase(i); } Thread.sleep(1000); } private static void increase(int i){ int1= i+1; int2= i+2; int3= i+3; int4= i+4; int5= i+5; }}
上面例子中,我们定义了5个int字段,然后在循环中对这些字段进行累加。
先看下javac编译出来的字节码的顺序:
我们可以看到在设置值的过程中是和java源代码的顺序是一致的,是按照int1,int2,int3,int4,int5的顺序一个一个设置的。
然后我们看一下生成的汇编语言代码:
在运行时添加参数-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly -XX:-Inline,或者直接使用JIT Watcher。
从生成的代码中,我们可以看到putstatic是按照int1,int5,int4,int3,int2的顺序进行的,也就是说进行了重排序。
如果我们将int2设置成为Volatile,看看结果如何?
前方高能预警,请小伙伴们做好准备
我们先看putstatic的顺序,从注释里面,我们只发现了putstatic int2, int3和int5。
要是没有能独立思考和独立决定的有创造个人,社会的向上发展就不可想像 – 爱因斯坦
这里是反编译的时候注释写错了!
让我们来仔细分析一下汇编代码。
第一个红框,不用懂汇编语言的朋友应该也可以看懂,就是分别给r11d,r8d,r9d,ecx和esi这5个寄存器分别加1,2,3,4,5。
这也分别对应了我们在increase方法中要做的事情。
有了这些寄存器的值,我们再继续往下看,从而可以知道,第二个红框实际上表示的就是putstatic int1,而最后一个红框,表示的就是putstatic int4。
所以,大家一定要学会自己分析代码。
5个putstatic都在,同时因为使用了volatile关键字,所以int2作为一个分界点,不会被重排序。所以int1一定在int2之前,而int3,4,5一定在int2之后。
上图的结果是在JIT Watcher中的C2编译器的结果,如果我们切换到C1编译器:
这次结果没错,5个int都在,同时我们看到这5个int居然没有重排序。
这也说明了不同的编译器可能对重排序的理解程度是不一样的。
写的内存屏障再来分析一下上面的putstatic int2:
lock addl $0x,-0x40(%rsp) ;*putstatic int2 {reexecute= rethrow= return_oop=}
这里使用了 lock addl指令,给rsp加了0。rsp是SP (Stack Pointer) register,也就是栈指针寄存器。
给rsp加0,是不是很奇怪?
加0,虽然没有改变rsp的值,但是因为前面加了lock,所以这个指令会被解析为内存屏障。
这个内存屏障保证了两个事情,第一,不会重排序。第二,所有的变量值都会回写到主内存中,从而在这个指令之后,变量值对其他线程可见。
当然,因为使用lock,可能对性能会有影响。
非lock和LazySet
上面我们提到了volatile会导致生成lock指令。
但有时候,我们只是想阻止重排序,对于变量的可见性并没有那么严格的要求。
这个时候,我们就可以使用Atomic类中的LazySet:
public class TestVolatile2 { private static int int1; private static AtomicInteger int2=new AtomicInteger(); private static int int3; private static int int4; private static int int5; public static void mAIn(String[] args) throws InterruptedException { for (int i = ; i < 10000; i++) { increase(i); } Thread.sleep(1000); } private static void increase(int i){ int1= i+1; int2.lazySet(i+2); int3= i+3; int4= i+4; int5= i+5; }}
从结果可以看到,int2没有重排序,也没有添加lock。
注意,上面的最后一个红框表示的是putstatic int4。
读的性能
最后,我们看下使用volatile关键字对读的性能影响:
public class TestVolatile3 { private static volatile int int1=10; public static void mAIn(String[] args) throws InterruptedException { for (int i = ; i < 10000; i++) { readInt(i); } Thread.sleep(1000); } private static void readInt(int i){ if(int1 < 5){ System.out.println(i); } }}
上面的例子中,我们对int1读取10000次。看下编译结果:
从结果可以看出,getstatic int1和不使用volatile关键字,生成的代码是一样的。
所以volatile对读的性能不会产生影响。
总 结
本文从汇编语言的角度再次深入探讨了volatile关键字和JMM模型的影响,希望大家能够喜欢。
猜你喜欢
- Excel会记住最近使用过的文件,并显示在“文件”菜单底部(Excel 2003)或“最近使用的文档”列表(Excel 2007
- 在使用win10系统时,若遇到可移动的鼠标却无法点击,鼠标不动时,先不要急。笔者认为Windows10系统的UAC设置窗口可以做一些调整,或
- 工作中有时为了需要,会将Excel表格中的一部分截出来供他人参考,如果手头上没有安装截图工具怎么办?下面就跟小编一起看看吧,欢迎大家来到学习
- 能够 许多人都 以为WPS 笔墨仅仅是 处置 笔墨的一款软件, 假如是 如许, 那末它附带的 画图 东西不是没 甚么用了?请不要 无视这些
- 我们通过对比 iPad Air 与 iPad 2018、iPad mini 以及 iPad Pro 11 寸,看看不同产品的差价究竟带来哪些
- WPS表格是金山办公套装软件的一个重要的组成部分,它可以进行各种数据的处理、统计分析和辅助决策操作;平时我们经常在WPS表格中用到SUM函数
- 行距是从一行文字的底部到另一行文字底部的间距,如:段落顶部间距、段落底部间距、文本行垂直间距的相关设置。1.选定要修改的文字。2.在“格式”
- excel中如何做到不填写指定单元格就无法填写另一个单元格。1、比如我们要设定不填写A1就无法填写C5。 2、先选
- 微软win10专业版系统因其稳定性和良好的兼容性而受到大家的喜爱。很多小伙伴不知道如何安装和下载微软win10专业版。今天,边肖带来了下载方
- Excel中的数据需要按照月份进行统计数据,用公式按照云粉统计数据具体该如何做到的呢?下面是由小编分享的excel按月统计数据的公式用法,以
- Word软件中怎么制作出同心圆效果操作教学。有的用户在制作文档的时候需要使用到同心圆的图案效果,那么这个效果要怎么制作,今天分享一下使用形状
- Excel软件中财务人员需要了解的常用技巧分享。财务人员在统计做账的时候,需要去了解一些操作技巧,这样可以帮助了极高的提高工作的效率,而且可
- 我们知道一个Excel表格中可以建立多个不同的表格,在办公的时候特别的方便,但有时我们可能会出现工作表的标签不见了的情况,今天,小编就向大家
- WPS Office 是一款更轻便、更易用、更简洁的办公软件,支持Word ,Excel,PPT,PDF主流文档格式,下面就来看看怎么开启文
- 我们在编辑Excel的时候总会遇到需要在表格里插入图片的情况,但是插入的图片很多时候在尺寸方面并不能让我们称心如意,那么有什么办法可以对图片
- Excel是三大办公软件之一的一个软件,他经常用于数据的整理、分析、以及对比等。而有很多时候需要用到Excel里画直线。下面是由小编分享的e
- excel怎么给某些单元格设置货币格式?想让某些单元格输入数据的时候直接显示货币格式,该怎么设置呢?今天我们就来看看给单元格数据设置格式的方
- 我们在利用WPS表格和Excel表格进行日常办公时,经常需要完成各种各样的表格,那么有时我们需要给表格当中的数字添加百分号,也就是用百分比的
- 一、在 咱们的WPS 笔墨软件中 翻开一篇含有照片的原始文档,,用鼠标选中图片,单击右键,在弹出的 快速菜单 当选择“ 配置 工具 格局”
- ①我们首先启动WPS表格,准备好数据源,在单元格输入公式:=LOOKUP(A2,{0,19.999,39.999,59.999,69.999