[讨论] 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?
    }
}

场景有些脑补,引起语义与结果不符的错误请忽略 ...只考虑重排序,不考虑可见性,VM的其它任何优化等规则不变,仅仅是所有操做都会走主内存
情况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
R大,xiaoyu哥 怎么突然都不回了呢?
做了张图,看看是这么个意思不?
xiaoyu 2012-10-23
runshine 写道
R大,xiaoyu哥 怎么突然都不回了呢?
做了张图,看看是这么个意思不?


因为我觉得你的答案是对的... 但是不知道有没有纰漏, 等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 最好是能把汇编指令和顺序显示出来, 再看...应该要清楚很多..
Global site tag (gtag.js) - Google Analytics