Volatile關鍵字原理 單例模式的雙重檢測

轉載請標明:https://www.cnblogs.com/tangZH/p/15113505.html

一、如果一個變量被volatile關鍵字修飾,那麼所有線程都是可見的。所謂可見就是,當一條線程修改了這個變量值,新值對於其他線程來時是立即可見的; 而普通變量不能做到這一點。

 

1、現在計算機緩存架構:

 

 CPU與內存之間存在緩存。

 

2、Java內存模型(JMM:java memory model)。

 

這裏的主內存再java中相當於堆。

 

在不同線程中操作同一個變量,實際上操作的是各自工作內存中的一個副本。

 

3、JMM的8大原子操作:

 

 

 4、過程:

當線程1需要用到變量a的時候,會通過read操作將a讀入臨時區,然後再通過load操作載入到變量副本中。

需要用這個變量的話就用use操作。

 

當線程2需要用到這個變量的時候也是一樣的過程。

如果變量沒有加volatile,那麼兩個線程用到的變量實際上是不一樣的。

 

 

加上volatile之後:

 

會強制將緩存刷新到主內.會激活總線嗅探器。當我們改變該變量在副本里面的值後寫回主內存時,總線監聽到就會去通知其餘線程將該變量的副本移除,然後再改變主內存中的值。這樣當其他線程再次用到該變量的時候就會重新從主內存裏面拿了。

 

總線嗅探器機制也被叫做MESI緩存一致性協議。

 

二、Volatile能夠禁止指令重排。

1、先看對象的生成過程,底層的指令如下:

 

 (1)、new 一個obj,此時內存裏面的初始值爲0.

 (2)、再棧裏面生成一個引用。

 (3)、執行構造方法,將值改變。

 (4)、將引用指向內存。

而編譯器會進行優化,編譯器優化是指,在不改變原來語義的情況下,通過調整語句順序,來讓程序運行的更快。比如將(3)、(4)交換順序不會有什麼影響(單線程情況下)。

 

具體例子看:

單例模式的雙重檢測

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章