R大有時會顛覆你Java的認知

關(guān)于volatile變量的內(nèi)存可見性,我在JVM群中拋出了一個問題,然后我的一些認知就被顛覆了。

問題

請教一個問題,a,b,c三個變量,其中c是volatile的,a,b是普通變量, a = 1, b = 2, c = 3, c寫入之后,a,b的值也會被刷入緩存嗎,還是c寫入之前所有在cpu緩存的數(shù)據(jù)都會被刷入內(nèi)存,還是只刷入和c在同一個緩存行的數(shù)據(jù)?

一開始,我的認知是后者,只刷入同一個緩存行的數(shù)據(jù)。

R大問答

你們要按happens before來考慮這種問題,不要整天無謂想著擦車(cache),Java的修正過的內(nèi)存模型其實基本點很簡單,同一線程內(nèi)的副作用按程序順序發(fā)生,所以a、b、c的賦值如果是在同一線程內(nèi)按這個順序?qū)懙?,實際執(zhí)行就要按照這個順序發(fā)生(至少表象上要按照這個順序;在程序無法感知順序差異時可以作弊)

這樣就是a賦值happens before b賦值,b賦值happens before c賦值,而不同線程之間的操作則是沒有happens before關(guān)系的,除非有volatile或者synchronized等帶有跨線程happen before關(guān)系的操作。不同線程之間的非volatile、非synchronized操作直接要想有傳遞的happens before關(guān)系的話,中間就肯定得有能產(chǎn)生happens before關(guān)系的volatile或者synchronized操作。

什么寄存器啊、緩存啊啥的不必扯進來。

我的反應(yīng)

哦~~~問號臉。。。

R大繼續(xù)解釋

JVM實現(xiàn)的時候是要把這些概念映射下去的(這里的概念應(yīng)該就是happens before),但是當你在思考高層程序語義的時候卻拿不合適的低層語義去解釋就很別扭,映射下去的辦法就是先有高層語義,然后看具體硬件上提供了哪些原語,然后再去實現(xiàn)。例如說在SPARC上它默認是TSO(total store order)的,在上面需要手工做的同步操作就很簡單。

曉銘大大的總結(jié)

JIT的時候會去查操作數(shù)的屬性,如果是volatile會在讀寫操作附近生成barrier的中間表示,最終barrier中間表示會變成什么指令,那要根據(jù)具體的機器,Memory consistency是一個spec,各種硬件系統(tǒng)包括cache都是實現(xiàn)的細節(jié)。

總結(jié)

總結(jié)起來,我這個問題問的不好,沒水準,問題直接從jmm跳到了硬件具體實現(xiàn),中間還隔著一層硬件的memory model。

所以緩存到底怎么刷,不同的CPU、不同廠商、不同型號實現(xiàn)可能都不一樣,一個人想了解所有似乎是個不可能的任務(wù),也不實用,只需要搞清楚JMM層面的東西就OK,管它到底怎么刷。

推廣

知識星球可以干什么?
1、【分享】高質(zhì)量的技術(shù)文章
2、【沉淀】「戰(zhàn)狼群」高質(zhì)量問題&解決方案
3、【成長】項目經(jīng)驗,生活隨筆,學習心得
4、【復(fù)盤】實戰(zhàn)經(jīng)驗,故障總結(jié)
5、【面經(jīng)】面試經(jīng)驗分享與總結(jié)
6、【推薦】技術(shù)書籍,崗位招聘

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容