1. 程式人生 > 其它 >12-Java指令重排序

12-Java指令重排序

Java指令重排序

  • Java記憶體模型允許編譯器和處理器對指令重排序以提高效能,並且只會對不存在的資料依懶性的指令進行重排序。在單執行緒下進行重排序可以保證最終執行的結果與程式順序執行的結果一致。但是在多執行緒下就會存在問題:下面看一個例子:

    int a=1;
    int b=2;
    int c=a+b;
    
  • 下面看一個多執行緒例子:

    package com.heiye.learn2;
    
    public class ReadThread extends Thread {
    
        private static int num=0;
        private static boolean ready=false;
    
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                if (ready) {
                    System.out.println(num + num);
                }
    
                System.out.println("read thread...");
            }
        }
    
        static class WriteThread extends Thread{
            @Override
            public void run() {
                num=2;
                ready=true;
                System.out.println("writeThread set over...");
            }
        }
    
        public static void main(String[] args) throws InterruptedException {
            ReadThread rt=new ReadThread();
            rt.start();
            WriteThread wt=new WriteThread();
            wt.start();
            Thread.sleep(10);
            rt.interrupt();
            System.out.println("main exit");
        }
    
    }
    

    首先這段程式碼裡面的變數沒有被宣告為volatile的,也沒有使用適合同步措施,所以在多執行緒下存在共共享變數可見性問題,這裡先不談記憶體可見性問題,因為通過把變數宣告為volatile的本身就可以避免指令重排問題。

  • 重排序在多執行緒下會導致非預期的程式執行結果,而是用volatile修飾變數就可以避免排序以及記憶體可見性問題。寫volatile變數的時候,可以確保volatile寫之前的操作不會被編譯器重新排序到寫之後,讀volatile變數時,可以確保volatile讀之後的操作不會被編譯器重新排序到volatile讀之前。