學習volatile:1. 保證可見性 2. 不保證原子性 3. 禁止指令重排

談談對volatile的理解

volatile是Java虛擬機提供的輕量級同步機制

  1. 保證可見性
  2. 不保證原子性
  3. 禁止指令重排
  1. 保證可見性
public class JMMDemo {
    // 不加 volatile 程序就會死循環!
    // 加 volatile 可以保證可見性
    private volatile static int num = 0;

    public static void main(String[] args) { // main

        new Thread(()->{ // 線程 1 對主內存的變化不知道的
            while (num==0){

            }
        }).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        num = 1;
        System.out.println(num);

    }
}
  1. 不保證原子性

原子性我們在學數據庫的時候有講過,就是不可分割,在這裏是指一個線程在執行任務的時候,是不能被打擾的,也不能被分割,要麼同時成功,要麼同時失敗。

// volatile 不保證原子性
public class VDemo02 {

    // volatile 不保證原子性
    // private volatile static int num=0;//用這行代碼的話輸出結果不是2萬
    // 我們知道加lock和synchronized可以保證原子性
    //如果不通過加鎖的話,來使volatile保證原子性,我們可以通過原子類的 Integer
    private volatile static AtomicInteger num = new AtomicInteger();

    public static void add(){
        // num++; // 不是一個原子性操作
        num.getAndIncrement(); // AtomicInteger + 1 方法, CAS
    }

    public static void main(String[] args) {

        //理論上num結果應該爲 2 萬
        for (int i = 1; i <= 20; i++) {
            new Thread(()->{
                for (int j = 0; j < 1000 ; j++) {
                    add();
                }
            }).start();
        }

        while (Thread.activeCount()>2){ // main  gc
            Thread.yield();
        }

        System.out.println(Thread.currentThread().getName() + " " + num);


    }
}

通過原子類 可以來解決volatile的不保證原子性問題,原子類的底層都是直接和操作系統掛鉤,在內存中直接修改值。
在這裏插入圖片描述

  1. 禁止指令重排

我們寫的代碼背後都是一個指令一個指令去執行的。

代碼的執行流程如下:
源代碼–>編譯器喲花的重排–>指令並行也可能重排–>內存系統也會重排–>執行
處理器在進行指令重排的時候,考慮:數據之間的依賴性

int x=1;//1
int y=2;//2
x=x+y;//3
y=y*y;//4

我們期望的結果是1234 但是可能執行的時候就變成2134 1324

可能造成的影響的結果:abxy這四個默認值都是0;

線程A 線程B
x=a y=b
b=1 a=2

正常的結果:x=0;y=0;但是看由於指令重排

線程A 線程B
b=1 a=2
x=a y=b

指令重排導致的詭異結果:x=2;y=1;

通俗講volatile可以避免指令重排
內存屏障,CPU指令,作用:

  1. 保證特定的執行順序
  2. 可以保證某些變量的內存可見性(利用這些特性實現了可見性)
    在這裏插入圖片描述

本文爲學習狂神說的JUC課程的筆記,課程地址:https://www.bilibili.com/video/BV1B7411L7tE?p=32

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章