内存屏障与JVM并发
2010-05-11 00:00:00 来源:WEB开发网PrintAssembly HotSpot选项是JVM的一个诊断标志,允许我们获取JIT编译器生成的汇编指令。这需要最新的OpenJDK版本或者新HotSpot update14或者更高版本。通过需要一个反编译插件。Kenai项目提供了用于Solaris、Linux和BSD的插件二进制文件。hsdis是另一款可以在Windows通过源码构建的插件。
两次顺序读操作的第一次(第三行)的汇编指令如下。指令流基于Itanium 2多处理硬件、JDK 1.6 update 17。本文的所有指令流都在左手边以行号标记。相关的读操作、写操作和内存屏障指令都以粗体标记。建议读者不要沉迷于每一行指令。
1 0x2000000001de819c: adds r37=597,r36;; ;...84112554
2 0x2000000001de81a0: ld1.acq r38=[r37];; ;...0b30014a a010
3 0x2000000001de81a6: nop.m 0x0 ;...00000002 00c0
4 0x2000000001de81ac: sxt1 r38=r38;; ;...00513004
5 0x2000000001de81b0: cmp4.eq p0,p6=0,r38 ;...1100004c 8639
6 0x2000000001de81b6: nop.i 0x0 ;...00000002 0003
7 0x2000000001de81bc: br.cond.dpnt.many 0x2000000001de8220;;
简短的指令流其实内容丰富。第一次volatile位于第二行。Java内存模型确保了JVM会在第二次读操作之前将第一次读操作交给处理器,也就是按照 “程序的顺序”——但是这单单一行指令是不够的,因为处理器仍然可以自由乱序执行这些操作。为了支持Java内存模型的一致性,JVM在第一次读操作上添加了注解ld.acq,也就是“载入获取”(load acquire)。通过使用ld.acq,编译器确保第二行的读操作在接下来的读操作之前完成。问题就解决了。
更多精彩
赞助商链接