1. volatile 保證了變數值修改的可見性
對於這一點,我們需要了解到在 java 中什麼是變數值。對於基本類型變數,變數值就是賦予它的數值,比如 int a=1,那麼 1 就是基本類型變數 a 的變數值。而對於引用變數類型,變數值就是堆棧中的地址,比如 Object a=new Object (),那麼 0x11111111 就是變數 a 的變數值。
綜上所述,對於基本類型變數,我們為其賦新的值就是修改了其變數值,比如 a=2;而對於引用變數類型,我們修改了其地址就是修改了其變數值,比如 a=new Object ()。
2. 數組類型保證內部元素的可見性
volatile int [] a = new int [4] 其實數組中的各個元素 a [0],a [1],a [2] 以及 a [3] 都具備可見性,而對於其可見性的判斷,可以參考第一條(因為數組中的每一個元素都可以看作是一個變數)。
3. volatile 變量賦值的新變量無法保證可見性
volatile Object a = new Object();
Object b = a;
其中 volatile 無法保證變量 b 的可見性。
在 concurrentHashMap 和 CopyOnWriteArrayList 中我們可以看到不同:
CopyOnWriteArrayList:
可以看到第一張圖中的 a 其實就是 array 本身,因此具備可見性,直接使用 a [index] 可以安全的獲取值。
concurrentHashMap:
其中我們通過第二張圖可以看到 table 被賦值給了一個新的變量 tab,儘管 table 本身被 volatile 修飾,但是新變量 tab 不具備可見性,因此需要使用 Unsafe 中的 getObjectVolatile 來安全地獲取值。