[讨论] reorder的几个疑问求解惑

runshine 2012-10-18
reorder发生的时间点是在哪个阶段?
1.源码编译成bytecode时
2.bytecode被载入vm时
3.(interpreted mode)bytecode到instruction的阶段
  (mixed mode)JIT生成native code时(或者是中间的某个阶段--比如汇编阶段),native code被执行时

---------------------------------------

volatile对reorder的影响
比如如下操作的顺序
int x1;
long x2;

volatile int y1;
volatile long y2;

int z1;
long z2;

reorder后
x系列与z系列,是否有可能被排到一起的可能(但是y系列之间的顺序不变化)?类似如下形式
long x2;
int x1;

int z1;
long z2;

volatile int y1;
volatile long y2;

还是说volatile作为内存屏障,只有其上界的代码之间(或下界的代码之间)会发生reorder而自身之间不会发生?类似如下形式
long x2;
int x1;

volatile int y1;
volatile long y2;

long z2;
int z1;

-------------------------------------------

[volatile|final]对可变对象可见性的影响
[volatile|final] HashMap<Long,Long> map;
不做任何的线程同步

线程1:
map.put(1L,1L);
map.put(2L,2L);
map.put(1L,-1L);
线程2是否会立即看到map的变化?

如果不能,如何才能让线程2立即看到变化?
[volatile|final] long y2;
线程1:
map.put(y2,y2);
可以吗?

--------------------------------------------
表述的不很清楚,希望不影响我表达的意思哈
RednaxelaFX 2012-10-18
runshine 写道
reorder发生的时间点是在哪个阶段?
1.源码编译成bytecode时
2.bytecode被载入vm时
3.(interpreted mode)bytecode到instruction的阶段
  (mixed mode)JIT生成native code时(或者是中间的某个阶段--比如汇编阶段),native code被执行时

规范没对这种细节做规定。只要最终的“表现”能维持规范所规定的顺序即可。
所以理论上以上所有情况都可以发生。

现实中的Java,
* 好多年之前开始Java源码编译到class文件的源码级编译器就已经不做重排序了。不是理论上不能做,只是投入-收益比不高所以大家都不做了而已。
* 类加载过程中会做字节码改写的VM不少见。至少HotSpot与JRockit都会对某些代码序列做改写,但不涉及重排序。
* 先对字节码做少量预处理/转换再解释执行的、以解释器来实现的JVM也是可以有的。如果在转换过程中做些重排序自然也是可以。不过HotSpot与J9都不做这个;JRockit不用解释器实现所以这里忽略。
* 从字节码到native code的动态编译时可能涉及大量重排序,HotSpot VM里的两个编译器所做的优化都有可能导致代码的重排,不过规范所规定的必须保证的同步/volatile顺序会有保证。
* CPU自身可能也是O-O-O(out-of-order)执行的。在这样的CPU上运行的JVM实现必须在合适的地方插入memory barrier来保证实际执行顺序与规范所规定的顺序一致。
runshine 2012-10-19
谢谢R大的解答.
分割线后的两个问题也无耻的恳请继续解答一下哈
xiaoyu 2012-10-19
runshine 写道
谢谢R大的解答.
分割线后的两个问题也无耻的恳请继续解答一下哈


我无耻的答一下. 对于一个复杂对象, 他整体结构上不能保证可见性, 你用volatile修饰引用是没用的.

所以 1, 和2 ....都是不可以的.
runshine 2012-10-19
xiaoyu 写道
runshine 写道
谢谢R大的解答.
分割线后的两个问题也无耻的恳请继续解答一下哈


我无耻的答一下. 对于一个复杂对象, 他整体结构上不能保证可见性, 你用volatile修饰他的引用是没用的.

所以 1, 和2 ....都是不可以的.


谢谢,谢谢~你说的是第三个问题哈?[1, 和2 ....]指的是
引用

1:
线程1:
map.put(1L,1L);
map.put(2L,2L);
map.put(1L,-1L);
线程2是否会立即看到map的变化?

2:
如果不能,如何才能让线程2立即看到变化?
[volatile|final] long y2;
线程1:
map.put(y2,y2);

这个么?
xiaoyu 2012-10-19
runshine 写道
xiaoyu 写道
runshine 写道
谢谢R大的解答.
分割线后的两个问题也无耻的恳请继续解答一下哈


我无耻的答一下. 对于一个复杂对象, 他整体结构上不能保证可见性, 你用volatile修饰他的引用是没用的.

所以 1, 和2 ....都是不可以的.


谢谢,谢谢~你说的是第三个问题哈?[1, 和2 ....]指的是
引用

1:
线程1:
map.put(1L,1L);
map.put(2L,2L);
map.put(1L,-1L);
线程2是否会立即看到map的变化?

2:
如果不能,如何才能让线程2立即看到变化?
[volatile|final] long y2;
线程1:
map.put(y2,y2);

这个么?


恩, 是你写的关于map, 1和2的两种可见性问题.
runshine 2012-10-19
xiaoyu 写道
恩, 是你写的关于map, 1和2的两种可见性问题.

哈哈~谢谢啦

还求第二个volatile对reorder影响问题的答案哈? 是第二种情况么?
xiaoyu 2012-10-19
runshine 写道
xiaoyu 写道
恩, 是你写的关于map, 1和2的两种可见性问题.

哈哈~谢谢啦

还求第二个volatile对reorder影响问题的答案哈? 是第二种情况么?



对于这个, 我只能说, jvm中class存储的数据结构顺序, 和执行(初始化)顺序...不是一回事...(能了解波?)

runshine 2012-10-19
xiaoyu 写道
runshine 写道
xiaoyu 写道
恩, 是你写的关于map, 1和2的两种可见性问题.

哈哈~谢谢啦

还求第二个volatile对reorder影响问题的答案哈? 是第二种情况么?



对于这个, 我只能说, jvm中class存储的数据结构顺序, 和执行(初始化)顺序...不是一回事...(能了解波?)


嗯...我不是这个意思,看来是我描述的太简略了.
那几个xyz,不是声明,而是对几种变量的操作的意思...
x系列是在第一次出现volatile之前的一系列操作,z系列是最后一次出现volatile之后的一系列操作,y系列是几个无关的volatile变量的操作
public class VolatileReorder
{
    int x1;
    long x2;
    int z1;
    long z2;
    volatile int y1;
    volatile long y2;

    public void exec(int arg)
    {
        x1 = arg+1;
        x2 = arg+2;

        y1 = arg+3;
        y2 = arg+4;

        z1 = arg+5;
        z2 = arg+6;
    }
}

就是这样,reorder可能导致的实际顺序是什么?
xiaoyu 2012-10-19
runshine 写道
xiaoyu 写道
runshine 写道
xiaoyu 写道
恩, 是你写的关于map, 1和2的两种可见性问题.

哈哈~谢谢啦

还求第二个volatile对reorder影响问题的答案哈? 是第二种情况么?



对于这个, 我只能说, jvm中class存储的数据结构顺序, 和执行(初始化)顺序...不是一回事...(能了解波?)


嗯...我不是这个意思,看来是我描述的太简略了.
那几个xyz,不是声明,而是对几种变量的操作的意思...
x系列是在第一次出现volatile之前的一系列操作,z系列是最后一次出现volatile之后的一系列操作,y系列是几个无关的volatile变量的操作
public class VolatileReorder
{
    int x1;
    long x2;
    int z1;
    long z2;
    volatile int y1;
    volatile long y2;

    public void exec(int arg)
    {
        x1 = arg+1;
        x2 = arg+2;

        y1 = arg+3;
        y2 = arg+4;

        z1 = arg+5;
        z2 = arg+6;
    }
}

就是这样,reorder可能导致的实际顺序是什么?


这个, R大已经回答你了. 仔细看. (PS: 看看cpu如何支持volatile的, 不同的操作对应不同的memory barrier, 那么reorder 就有不同的规定的..)
Global site tag (gtag.js) - Google Analytics