Java虛擬機器——Java記憶體模型與執行緒 [待更新]
12.2硬體的效率與一致性
處理器與記憶體速度矛盾-->
1.引入快取記憶體-->新的問題:快取一致性(Cache Coherence)
2.指令重排優化( Instruction Reorder)
保證結果與順序執行結果一致,但不保證程式中各個語句計算先後順序與輸入程式碼的順序一致.
12.3 Java記憶體模型( Java Memory Model, JMM)
遮蔽屌各種硬體和作業系統的記憶體訪問差異,以實現讓Java程式在各種平臺下都能達到一致的記憶體訪問效果.
12.3.3 volatile型變數的特殊規則
1.保證此變數對所有執行緒的可見性.(
2.禁止指令重排優化.
對於第二點,有一個非常經典的例子就是DCL (double check lock)的使用.
如下:
public static SingletongetInstance()
{
if (instance == null)
{
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
}
return instance;
}
因為Instruction Reorder
這句假設分為三步
1.先申請記憶體 2.構造Singleton
3.將instance指向新的記憶體區域如果不進行指令重排,這個是沒問題的.
如果指令重排後執行順序是. 1 3 2.這就導致執行3後,instance已經非null,此時若恰好有別的執行緒重新訪問get_instance函式.將得到instance非null的結果,並此時返回一個還沒執行完建構函式的instance例項.從而出錯.
但是volatile關鍵字的第二個語義,便是‘禁止指令重排優化’.
因此,如果把instance變數宣告為
volatile ,
如下:
private static volatile Singleton instance;
12.3.5 原子性可見性 有序性
12.3.6 先行發生原則
1.程式次序規則(控制流順序)
2.管程鎖定規則(同一個鎖中unlock先於下一個lock)
3.volatile變數規則(寫操作先於讀操作)
4.執行緒啟動規則
5.執行緒終止規則
6.執行緒中斷規則
7.物件終結規則
8.傳遞性
12.4 Java與執行緒
13.2 執行緒安全
13.2.1五類劃分
13.2.2實現執行緒安全的方法
1互斥同步
Synchronize關鍵字
1.synchronize同步塊對同一執行緒是可重入的,不會鎖死自己
2.同步塊在已進入的執行緒執行完之前,會阻塞後面的其他執行緒進入
3.阻塞或喚醒執行緒需要從使用者態轉到和心態,因此可能耗費很多時間, synchronize是一個重量級(Heavyweight)的操作
2 非阻塞同步
13.3鎖優化
1.自旋鎖與自適應自旋(忙迴圈以避免掛起,恢復執行緒)
2.鎖消除 (虛擬機器的優化)
3.鎖粗化 (避免頻繁lock與unlock)
4.輕量輕鎖
5.偏向鎖