原子性、可見性、有序性、
(1)原子性
原子性是指一個操作是不可中斷的,要麼全部執行成功要麼全部執行失敗
```javascript
Int a = 10; //原子性
a++; //1.讀取a的值 2.對a+1 3.更新的值賦給a
Int b = a; //1.讀取a 2.將a賦給b
a = a+1;
```
java內存模型中定義了8中操作都是原子的
- lock(鎖定):作用於主內存中的變量,它把一個變量標識爲一個線程獨佔的狀態;
- unlock(解鎖):作用於主內存中的變量,它把一個處於鎖定狀態的變量釋放出來,釋放後的變量纔可以被其他線程鎖定
- read(讀取):作用於主內存的變量,它把一個變量的值從主內存傳輸到線程的工作內存中,以便後面的load動作使用;
- load(載入):作用於工作內存中的變量,它把read操作從主內存中得到的變量值放入工作內存中的變量副本
- use(使用):作用於工作內存中的變量,它把工作內存中一個變量的值傳遞給執行引擎,每當虛擬機遇到一個需要使用到變量的值的字節碼指令時將會執行這個操作;
- assign(賦值):作用於工作內存中的變量,它把一個從執行引擎接收到的值賦給工作內存的變量,每當虛擬機遇到一個給變量賦值的字節碼指令時執行這個操作;
- store(存儲):作用於工作內存的變量,它把工作內存中一個變量的值傳送給主內存中以便隨後的write操作使用;
- write(操作):作用於主內存的變量,它把store操作從工作內存中得到的變量的值放入主內存的變量中。
java內存模型只是要求上述兩個操作是順序執行的並不是連續執行的。
(2)有序性
public class Singleton {
private Singleton() { }
private volatile static Singleton instance;
public Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
}
使用這個雙重校驗鎖例子說明有序性
關鍵在於 instance = new Singleton();
實際上這條語句包含是三個操作
1.分配對象的內存空間;
2.初始化對象;
3.設置instance指向剛分配的內存地址
但是因爲重排序的問題 有可能會發生執行順序錯誤
如果2和3進行重排序執行順序變爲 1 3 2
在多線程的情況下線程B先進行判斷if(instance==null)會爲true
實際上instance並沒有初始化對於B來說並沒有爲對象分配空間
volatile包含禁止指令重排序的語義,其具有有序性。
(3)可見性
可見性是指當一個線程修改了共享變量後,其他線程能夠立即得知這個修改。
對synchronzed內存語義進行了分析,當線程獲取鎖時會從主內存中獲取共享變量的最新值,釋放鎖的時候會將共享變量同步到主內存中。
synchronized: 具有原子性,有序性和可見性; volatile:具有有序性和可見性