武漢java培訓
達內武漢中心

18571612865

熱門課程

請問volatile 如何保證有序性

  • 時間:2018-09-11 16:19
  • 發布:武漢java培訓
  • 來源:互聯網

Java 內存模型具備一些先天的“有序性”,即不需要通過任何手段就能夠得到保證的有序性,這個通常也稱為 happens-before 原則。如果兩個操作的執行次序無法從 happens-before 原則推導出來,那么它們就不能保證它們的有序性,虛擬機可以隨意地對它們進行重排序。

武漢java培訓

這里主要說一下 volatile 關鍵字的規則,舉一個著名的單例模式中的雙重檢查的例子:

class Singleton{

private volatile static Singleton instance = null;

private Singleton() {

}

public static Singleton getInstance() {

if(instance==null) { // step 1

synchronized (Singleton.class) {

if(instance==null) // step 2

instance = new Singleton(); //step 3

}

}

return instance;

}

}

如果 instance 不用 volatile 修飾,可能產生什么結果呢,假設有兩個線程在調用 getInstance() 方法,線程 1 執行步驟 step1 ,發現 instance 為 null ,然后同步鎖住 Singleton 類,接著再次判斷 instance 是否為 null ,發現仍然是 ull,然后執行 step 3 ,開始實例化 Singleton 。而在實例化的過程中,線程 2 走到 step 1,有可能發現 instance 不為空,但是此時 instance 有可能還沒有完全初始化。

什么意思呢,對象在初始化的時候分三個步驟,用下面的偽代碼表示:

memory = allocate(); //1. 分配對象的內存空間

ctorInstance(memory); //2. 初始化對象

instance = memory; //3. 設置 instance 指向對象的內存空間

因為步驟 2 和步驟 3 需要依賴步驟 1,而步驟 2 和 步驟 3 并沒有依賴關系,所以這兩條語句有可能會發生指令重排,也就是或有可能步驟 3 在步驟 2 的之前執行。在這種情況下,步驟 3 執行了,但是步驟 2 還沒有執行,也就是說 instance 實例還沒有初始化完畢,正好,在此刻,線程 2 判斷 instance 不為 null,所以就直接返回了 instance 實例,但是,這個時候 instance 其實是一個不完全的對象,所以,在使用的時候就會出現問題。

而使用 volatile 關鍵字,也就是使用了 “對一個 volatile修飾的變量的寫,happens-before于任意后續對該變量的讀” 這一原則,對應到上面的初始化過程,步驟2 和 3 都是對 instance 的寫,所以一定發生于后面對 instance 的讀,也就是不會出現返回不完全初始化的 instance 這種可能。

本篇文章是有武漢Java培訓機構為您呈現,希望給您帶來更多更好的文章,請掃描下方二維碼

武漢Java培訓機構

馬上預約七天免費試聽課

姓名:

電話:

上一篇:有關有序數組的算法詳解
下一篇:第十二屆達內校企合作高峰論壇重點全回顧
選擇城市和中心
江西省

貴州省

廣西省

海南省

有位老師想和您聊一聊

中文字幕无线观看不卡网站