volatile修饰符会破坏jvm优化么

2017-07-12  本文已影响31人  battle_

effective java第66条,同步访问共享变量的一个例子
例如

public class VolatileTest {
    private static boolean testBool;

    public static void main(String[] args) throws InterruptedException {
        Thread test = new Thread(new Runnable(){
            public void run(){
                int i = 0;
                while(!testBool){
                    i++;
                }
            }
        });
        
        test.start();
        TimeUnit.SECONDS.sleep(1);
        testBool = true;

    }

}

书中说虚拟机会将代码优化hoisting

if(!testBool){
  while(true) i++
}

而导致该进程操作无法停止

可以使用sync关键字同步读写testBool变量,从而达想要的通信效果

也可以使用volatile修饰符修饰testBool,该修饰符会强制线程复制的共享变量值一直为共享池中的最新值。
但是如果JVM仍然进行hoisting优化,效果应该是不正确的。而实际效果是正确的。可能是volatile修饰符强行终止了JVM优化。
volatile并不能实现同步互斥,只是让线程一直获取最新的共享内容,只能保证对单次读/写的原子性,像i++这种操作是读和写两次操作,读取i,对i+1,写入i。

测试发现,在i++后执行一个System.out.println("i" + i);内容也会发生VM没有进行优化操作,代码在主线程执行完赋值就终止了。
而且翻阅网络上的文章,发现VM使用client模式也不会复现优化后的场景,只有server模式VM才可以复现

上一篇下一篇

猜你喜欢

热点阅读