1.volatile的應(yīng)用
在多線程并發(fā)編程中synchronized和volatile都扮演這重要角色务豺,volatile是輕量級(jí)的synchronized退敦,他在多處理開發(fā)中保證了共享變量的“可見(jiàn)性”隆嗅〖袅猓可見(jiàn)性的意識(shí)是當(dāng)一個(gè)線程修改了一個(gè)共享變量時(shí)浪耘,另外一個(gè)線程能讀到這個(gè)修改的值症汹。如果volatile變量修飾符使用恰當(dāng)?shù)脑挶龇危萻ynchronized的使用和執(zhí)行成本更低溯饵,因?yàn)樗粫?huì)引起線程上下文的切換和調(diào)度。
2.volatile的定義和實(shí)現(xiàn)原理
java語(yǔ)言規(guī)范第3版中對(duì)volatile的定義如下:java編程語(yǔ)言允許線程訪問(wèn)共享變量锨用,為了確保共享變量能被準(zhǔn)確和一致地更新丰刊,線程應(yīng)該確保排他鎖單獨(dú)獲得這個(gè)變量。
java語(yǔ)言提供了volatile增拥,在某些情況下比鎖更加方便啄巧。如果一個(gè)字段被聲明成volatile,java線程內(nèi)存模型確保所有線程看到這個(gè)變量的值是一致的。
在了解volatile實(shí)現(xiàn)原理之前掌栅,我們先來(lái)看下與其原理相關(guān)的CPU術(shù)語(yǔ)與說(shuō)明秩仆。
volatile是如何保證可見(jiàn)性的呢?有volatile修飾的共享變量進(jìn)行寫操作時(shí)會(huì)多出一行匯編語(yǔ)言(lock前綴的指令)猾封,這行指令會(huì)引發(fā)兩件事情
1)將當(dāng)前處理器緩存行的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存澄耍。
2)這個(gè)寫回內(nèi)存的操作會(huì)使其在其他CPU里緩存了該內(nèi)存地址的數(shù)據(jù)無(wú)效
為了提高處理器速度,處理器不直接和內(nèi)存進(jìn)行通信晌缘,而是先將系統(tǒng)內(nèi)存的數(shù)據(jù)讀到內(nèi)部緩存(L1,L2或其他)后再進(jìn)行操作齐莲,但操作完不知道何時(shí)寫回到內(nèi)存。如果對(duì)聲明了volatile的變量進(jìn)行寫操作磷箕,JVM就會(huì)想處理器發(fā)送一條Lock前綴的指令选酗,將這個(gè)變量所在緩存行的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存。但是搀捷,就算寫回到內(nèi)存星掰,如果其他處理器緩存的值還是舊的多望,在執(zhí)行計(jì)算就會(huì)有問(wèn)題。所以氢烘,在多處理器下怀偷,為了保證各個(gè)處理器的緩存是一致的,就會(huì)實(shí)現(xiàn)緩存一致性協(xié)議播玖,每個(gè)處理里通過(guò)嗅探在總線上傳播的數(shù)據(jù)來(lái)檢查自己緩存的值是不是過(guò)期了椎工,當(dāng)處理器發(fā)現(xiàn)自己緩存行對(duì)應(yīng)的內(nèi)存地址被修改,就會(huì)將當(dāng)前處理器的緩存行設(shè)置為無(wú)效狀態(tài)蜀踏,當(dāng)處理器對(duì)這個(gè)數(shù)據(jù)進(jìn)行修改操作的時(shí)候维蒙,會(huì)重新從系統(tǒng)內(nèi)存中把數(shù)據(jù)讀到處理器緩存里。