TOP

Java内存模型与指令重排(三)
2018-06-09 10:07:57 】 浏览:675
Tags:Java 内存 模型 指令

bsp;       ;*goto
                                        ; - VisibilityTest::run@12 (line 10)
  0x02b48971: test  %edi,0xb30000      ;*aload_0
                                        ; - VisibilityTest::run@2 (line 9)
                                        ;  {poll}
  // 循环过程中获取stop的值
  0x02b48977: movzbl 0x64(%ebp),%eax    ;*getfield stop
                                        ; - VisibilityTest::run@3 (line 9)
  // 验证stop的值
  0x02b4897b: test  %eax,%eax
  // 若stop不符合条件, 则继续跳转到0x02b48970: inc, 执行i++, 否则中断循环
  0x02b4897d: je    0x02b48970        ;*ifne
                                        ; - VisibilityTest::run@6 (line 9)
  0x02b4897f: mov    $0x33,%ecx
  0x02b48984: mov    %ebx,%ebp
  0x02b48986: nop   
  // 跳出循环, 执行System.out.print打印
  0x02b48987: call  0x02b2cac0        ; OopMap{off=76}
                                        ;*getstatic out
                                        ; - VisibilityTest::run@15 (line 12)
                                        ;  {runtime_call}
  0x02b4898c: int3 
  0x02b4898d: mov    $0xffffff9d,%ecx
  ......


再来看两个从Java语言规范中摘取的例子, 也是涉及到编译器优化重排, 这里不再做详细解释, 只说下结果.


例子1中有可能出现r2 = 2 并且 r1 = 1;



例子2中是r2, r5值因为都是=r1.x, 编译器会使用向前替换, 把r5指向到r2, 最终可能导致r2=r5=0, r4 = 3;



如果光靠sychronized和volatile来保证程序执行过程中的原子性, 有序性, 可见性, 那么代码将会变得异常繁琐.


JMM提供了Happen-Before规则来约束数据之间是否存在竞争, 线程环境是否安全, 具体如下:


顺序原则


一个线程内保证语义的串行性; a = 1; b = a + 1;


volatile规则


volatile变量的写,先发生于读,这保证了volatile变量的可见性,


锁规则


解锁(unlock)必然发生在随后的加锁(lock)前.


传递性


A先于B,B先于C,那么A必然先于C.


线程启动, 中断, 终止


线程的start()方法先于它的每一个动作.


线程的中断(interrupt())先于被中断线程的代码.


线程的所有操作先于线程的终结(Thread.join()).


对象终结


对象的构造函数执行结束先于finalize()方法.



Java内存模型与指令重排(三) https://www.cppentry.com/bencandy.php?fid=54&id=170261

首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java高并发之无锁与Atomic源码分析 下一篇Spring MVC接收数组类型参数