Java指令重排序——源自《Java并发编程之美》

Java内存模型允许编译期和处理器对执行重排序以提高运行性能,并且只会对不存在数据依赖性的指令重排序。在单线程下重排序可以保证最终执行的结果与程序顺序执行的结果一直,但是在多线程下就会存在问题。

举例:



```Java
public class ReadThread extends Thread {
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()){
            if (ready){ // (1)
                System.out.println(num+num); // (2)
            }
            System.out.println("read thread......");
        }
    }
    public static class WriteThread extends Thread{
        @Override
        public void run() {
            num =2; // (3)
            ready = true; // (4)
            System.out.println("writeThread set over......");
        }
    }

    private static int num = 0;
    private static boolean ready = false;

    public static void main(String[] args) throws InterruptedException {
        ReadThread readThread = new ReadThread();
        readThread.start();
        WriteThread writeThread = new WriteThread();
        writeThread.start();
        Thread.sleep(10);
        readThread.interrupt();
        System.out.println("main exit");
    }
}
```

该段代码没有变量被声明为volatile,也没有采取同步措施,所以在多线程下存在共享变量内存可见性问题。这里先不谈内存可见性问题,因为通过把变量声明为volatile的本身就可以避免指令重排序问题。

在如上代码不考虑内存可见性问题的情况下不一定会输出4。由于(1)(2)(3)(4)之间不存在依赖关系,所以写线程的(3)(4)可能被重排序为先执行(4)再执行(3),那么执行(4)后,读线程可能已经执行的(1)操作,并在(3)执行前开始执行(2)操作,这时候输出的结果为0而不是4

重排序在多线程下会导致非预期的程序执行结果,而是用volatile修饰ready就可以避免重排序和内存可见性问题

 

摘自《Java并发编程之美》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值