內(nèi)存屏障
由于現(xiàn)代的操作系統(tǒng)都是多處理器.而每一個(gè)處理器都有自己的緩存,并且這些緩存并不是實(shí)時(shí)都與內(nèi)存發(fā)生信息交換.這樣就可能出現(xiàn)一個(gè)cpu上的緩存數(shù)據(jù)與另一個(gè)cpu上的緩存數(shù)據(jù)不一致的問(wèn)題.而這樣在多線(xiàn)程開(kāi)發(fā)中,就有可能導(dǎo)致出現(xiàn)一些異常行為.
而操作系統(tǒng)底層為了這些問(wèn)題,提供了一些內(nèi)存屏障用以解決這樣的問(wèn)題.目前有4種屏障.
LoadLoad屏障:對(duì)于這樣的語(yǔ)句Load1; LoadLoad; Load2,在Load2及后續(xù)讀取操作要讀取的數(shù)據(jù)被訪(fǎng)問(wèn)前尽超,保證Load1要讀取的數(shù)據(jù)被讀取完畢观挎。
StoreStore屏障:對(duì)于這樣的語(yǔ)句Store1; StoreStore; Store2朋凉,在Store2及后續(xù)寫(xiě)入操作執(zhí)行前叹放,保證Store1的寫(xiě)入操作對(duì)其它處理器可見(jiàn)怜跑。
LoadStore屏障:對(duì)于這樣的語(yǔ)句Load1; LoadStore; Store2沼沈,在Store2及后續(xù)寫(xiě)入操作被刷出前单绑,保證Load1要讀取的數(shù)據(jù)被讀取完畢。
StoreLoad屏障:對(duì)于這樣的語(yǔ)句Store1; StoreLoad; Load2,在Load2及后續(xù)所有讀取操作執(zhí)行前城榛,保證Store1的寫(xiě)入對(duì)所有處理器可見(jiàn)揪利。它的開(kāi)銷(xiāo)是四種屏障中最大的。在大多數(shù)處理器的實(shí)現(xiàn)中狠持,這個(gè)屏障是個(gè)萬(wàn)能屏障疟位,兼具其它三種內(nèi)存屏障的功能。
使用
java中對(duì)內(nèi)存屏障的使用在一般的代碼中不太容易見(jiàn)到.常見(jiàn)的有兩種.
通過(guò) Synchronized關(guān)鍵字包住的代碼區(qū)域,當(dāng)線(xiàn)程進(jìn)入到該區(qū)域讀取變量信息時(shí),保證讀到的是最新的值.這是因?yàn)樵谕絽^(qū)內(nèi)對(duì)變量的寫(xiě)入操作,在離開(kāi)同步區(qū)時(shí)就將當(dāng)前線(xiàn)程內(nèi)的數(shù)據(jù)刷新到內(nèi)存中,而對(duì)數(shù)據(jù)的讀取也不能從緩存讀取,只能從內(nèi)存中讀取,保證了數(shù)據(jù)的讀有效性.這就是插入了StoreStore屏障
使用了volatile修飾變量,則對(duì)變量的寫(xiě)操作,會(huì)插入StoreLoad屏障.
其余的操作,則需要通過(guò)Unsafe這個(gè)類(lèi)來(lái)執(zhí)行.
Unsafe中內(nèi)存屏障的使用
UNSAFE.putOrderedObject類(lèi)似這樣的方法,會(huì)插入StoreStore內(nèi)存屏障
Unsafe.putVolatiObject 則是插入了StoreLoad屏障