相?synchronized的加鎖?式來解決共享變量的內(nèi)存可?性問題,volatile就是更輕量的選擇,他沒有上
下?切換的額外開銷成本。使?volatile聲明的變量,可以確保值被更新的時候?qū)ζ渌€程?刻可?。
volatile使?內(nèi)存屏障來保證不會發(fā)?指令重排,解決了內(nèi)存可?性的問題。
我們知道,線程都是從主內(nèi)存中讀取共享變量到?作內(nèi)存來操作,完成之后再把結(jié)果寫會主內(nèi)存,但是
這樣就會帶來可?性問題。舉個例?,假設(shè)現(xiàn)在我們是兩級緩存的雙核CPU架構(gòu),包含L1、L2兩級緩
存。
1. 線程A?先獲取變量X的值,由于最初兩級緩存都是空,所以直接從主內(nèi)存中讀取X,假設(shè)X初始值為
0,線程A讀取之后把X值都修改為1,同時寫回主內(nèi)存。這時候緩存和主內(nèi)存的情況如下圖。

2. 線程B也同樣讀取變量X的值,由于L2緩存已經(jīng)有緩存X=1,所以直接從L2緩存讀取,之后線程B把X
修改為2,同時寫回L2和主內(nèi)存。這時候的X值?下圖所示。
那么線程A如果再想獲取變量X的值,因為L1緩存已經(jīng)有x=1了,所以這時候變量內(nèi)存不可?問題就
產(chǎn)?了,B修改為2的值對A來說沒有感知。

那么,如果X變量?volatile修飾的話,當(dāng)線程A再次讀取變量X的話,CPU就會根據(jù)緩存?致性協(xié)議強制
線程A重新從主內(nèi)存加載最新的值到??的?作內(nèi)存,?不是直接?緩存中的值。
再來說內(nèi)存屏障的問題,volatile修飾之后會加?不同的內(nèi)存屏障來保證可?性的問題能正確執(zhí)?。這?
寫的屏障基于書中提供的內(nèi)容,但是實際上由于CPU架構(gòu)不同,重排序的策略不同,提供的內(nèi)存屏障也
不?樣,?如x86平臺上,只有StoreLoad?種內(nèi)存屏障。
1. StoreStore屏障,保證上?的普通寫不和volatile寫發(fā)?重排序
2. StoreLoad屏障,保證volatile寫與后?可能的volatile讀寫不發(fā)?重排序
3. LoadLoad屏障,禁?volatile讀與后?的普通讀重排序
4. LoadStore屏障,禁?volatile讀和后?的普通寫重排序
