1. 程式人生 > >Java虛擬機器——Java記憶體模型與執行緒 [待更新]

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

的關係,其中的instance=new Singleton ()會出一點問題:

這句假設分為三步
1.
先申請記憶體 2.構造Singleton 3.instance指向新的記憶體區域如果不進行指令重排,這個是沒問題的.
如果指令重排後執行順序是. 1 3 2.這就導致執行3,instance已經非null,此時若恰好有別的執行緒重新訪問get_instance函式.將得到instancenull的結果,並此時返回一個還沒執行完建構函式的instance例項.從而出錯.
但是volatile關鍵字的第二個語義,便是禁止指令重排優化’.
因此,如果把instance變數宣告為 volatile ,

雙重檢測法似乎也是work.
如下:

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.鎖粗化 (避免頻繁lockunlock)

4.輕量輕鎖

5.偏向鎖