[讨论] reorder的几个疑问求解惑
runshine
2012-10-19
xiaoyu 写道 这个, R大已经回答你了. 仔细看. (PS: 看看cpu如何支持volacity的, 不同的操作对应不同的memory barrier, 那么reorder 就有不同的规定的..)
引用 不过规范所规定的必须保证的同步/volatile顺序会有保证。
在这样的CPU上运行的JVM实现必须在合适的地方插入memory barrier来保证实际执行顺序与规范所规定的顺序一致。 是指这两句么? 意思能明白,只是结论总有些模糊.有些不敢确定的地方 比如(以下只考虑重排序,而不考虑可见性问题,相应的jvm依然是以前的优化规则,就是把可见性问题取消,任何操作均会对主内存操作,场景有些脑补...): 情况1: 引用 class VR { public static int i1=0; public static int i2=0; public static volatile int i3=0; public static volatile int i4=0; } 线程1做两个赋值操作 i1=1; i2=2; 线程2: for(;;) { if(i2==2) { System.out.println(i1); //有输出 0 的可能; } } 情况2: 引用 class VR { public static int i1=0; public static int i2=0; public static volatile int i3=0; public static volatile int i4=0; } 线程1做两个赋值操作 i3=3; i4=4; 线程2: for(;;) { if(i4==4) { System.out.println(i3); //是否会输出0? } } 情况3: 引用 class VR { public static int i1=0; public static int i2=0; public static volatile int i3=0; public static volatile int i4=0; } 线程1做两个赋值操作 i2=2; i4=4; 线程2: for(;;) { if(i4==4) { System.out.println(i2); //是否会输出0? } } 情况4: 引用 class VR { public static int i1=0; public static int i2=0; public static volatile int i3=0; public static volatile int i4=0; } 线程1做如下赋值操作 i1=1; i3=3; i4=4; i2=2; 线程2: for(;;) { if(i2==2) { System.out.println(i1); //是否会输出0? } } 场景有些脑补,引起语义与结果不符的错误请忽略 ![]() 情况1很明显有输出0的可能,情况2应该不会输出0 情况3、4呢? |
|
runshine
2012-10-19
上边脑补了个有点玄幻的场景...
![]() 其实就是想说,在有对volatile变量操作的地方,JVM就会插入内存屏障,且范围仅在volatile变量被操作的这条指令内,对其上界以上或下界以下的优化操作没有影响(上界以上或下界以下的操作该怎么重排就怎么重拍,但无法越过屏障)。是不是这样呢? 由此还引申出一个问题,同时也是另外一人的帖子(http://heavensay.iteye.com/blog/1455349)中提到的问题: java中,volatile 指令前面的一些内存操作,会不会在这个volatile相关指令执行的时候,volatile修饰的变量写回到内存中的时候,那些 no-volatile变量的内存是否也会写回到内存中?而不是保留在java的工作内存中? 1.如果jvm、jit也像上面内容一样的插入诸如 mb(),rmb()等相关的内存屏障指令的话,那么no-volatile变量,是否会写回到主内存中? 2.还有就是X86的写是顺序的,X86下的java是否可以不用考虑reorder的问题? 上面两个问题是否因为平台相关(是与机器相关?还是与OS相关?还是与屏障的实现相关?或者是以上相关的交集或补集?)以及内存屏障并不保证是否一定会回写内存(读屏障、写屏障、通用屏障、优化屏障(优化屏障则用于限制编译器的指令重排)),所以在java下我们将这种条件视为不存在,应该忽视的? |
|
runshine
2012-10-22
![]() 做了张图,看看是这么个意思不? ![]() |
|
xiaoyu
2012-10-23
runshine 写道 ![]() 做了张图,看看是这么个意思不? ![]() 因为我觉得你的答案是对的... 但是不知道有没有纰漏, 等R大回答吧. |
|
xiaoyu
2012-10-23
runshine 写道 上边脑补了个有点玄幻的场景...
![]() 其实就是想说,在有对volatile变量操作的地方,JVM就会插入内存屏障,且范围仅在volatile变量被操作的这条指令内,对其上界以上或下界以下的优化操作没有影响(上界以上或下界以下的操作该怎么重排就怎么重拍,但无法越过屏障)。是不是这样呢? 由此还引申出一个问题,同时也是另外一人的帖子(http://heavensay.iteye.com/blog/1455349)中提到的问题: java中,volatile 指令前面的一些内存操作,会不会在这个volatile相关指令执行的时候,volatile修饰的变量写回到内存中的时候,那些 no-volatile变量的内存是否也会写回到内存中?而不是保留在java的工作内存中? 1.如果jvm、jit也像上面内容一样的插入诸如 mb(),rmb()等相关的内存屏障指令的话,那么no-volatile变量,是否会写回到主内存中? 2.还有就是X86的写是顺序的,X86下的java是否可以不用考虑reorder的问题? 上面两个问题是否因为平台相关(是与机器相关?还是与OS相关?还是与屏障的实现相关?或者是以上相关的交集或补集?)以及内存屏障并不保证回写内存(读屏障、写屏障、通用屏障、优化屏障(优化屏障则用于限制编译器的指令重排)),所以在java下我们将这种条件视为不存在,应该忽视的? 看jsr133 规范说 volatile 有 acquire 和 release 语义. 如果我了解没错, 那么应该是会回写的.(等 R 大确认一下吧) PS: reorder 最好是能把汇编指令和顺序显示出来, 再看...应该要清楚很多.. |