1. 程式人生 > 其它 >6.22Java多執行緒volitale

6.22Java多執行緒volitale

6.22Java多執行緒volitale

volitale說明

作用:

保證執行緒間變數的可見性(注意:不是執行緒之間的變數可見)

執行緒A對變數X進行修改後,線上程A後面執行的其他執行緒能看到變數X的變動。

需要符合以下兩個規則:

  • 執行緒對變數進行修改之後要立刻寫回到主記憶體--->防止主記憶體與工作記憶體中不一致的情況

    • 加了volitale修飾,對變數的修改就會立刻寫到主記憶體當中

    • 同時通知另一個執行緒拿到最新的

  • 執行緒對變數讀取的時候要從主記憶體中讀,而不是從快取中讀

執行緒工作模式圖:

特點:

  • 各執行緒的工作記憶體間彼此獨立、互不可見。

  • 線上程啟動的時候,虛擬機器為每個記憶體分配一塊工作記憶體。

    • 包含了執行緒內部定義的區域性變數

    • 執行緒所需要使用的共享變數(非執行緒內構造的物件)的副本

volatile的缺陷:--->只保證了同步的資料可見

volatile不能保證原子性

什麼是原子性?

以程式碼a++舉例,在彙編層面會分成三步

  1. 拿到a

  2. a+1計算結果

  3. 儲存計算的結果到a中

這完整的三步是一個整體、一個變數。--->volatile不能保證這三個作為一個整體發生變化

volatile例項demo
package thread.rearrangement;

/**
* volatile用於保證資料的同步
* 可見性
* 粒度很小,只保證資料的同步
* 不保證原子性,可以避免指令重排!!!
* @since JDk 1.8
* @date 2021/6/22
* @author Lucifer
*/
public class VolatileTestNo1 {

/*加一個類變數*/
private volatile static int num = 0;

public static void main(String[] args) {

/*使用lambda表示式多執行緒操作變數*/
new Thread(() -> {
/*寫一個死迴圈*/
while (num==0){
//這裡不要編寫程式碼--->目的是讓cpu繁忙
}
}).start();

/*一秒後改變值為1*/
try {
Thread.sleep(1000);
}catch (InterruptedException e){
System.out.println(e.getMessage());
e.printStackTrace();
}

/*改變變數的值*/
num = 1;

}
/*
如果不加volatile那麼執行緒不會停止
加了volatile以後一秒後num已經發生改變,雖然不會回顯(因為事務沒有回寫到主存)但是執行緒一樣會停止
保證資料的可見性,保證資料的重排
不保證賦值操作的原子性
*/
}