2 回答

TA貢獻(xiàn)1880條經(jīng)驗(yàn) 獲得超4個(gè)贊
CPU 緩存中的值多久與主內(nèi)存刷新/同步一次?
不明確的。當(dāng) JLS 中指定的可見性保證表明需要發(fā)生緩存刷新時(shí),就會(huì)發(fā)生緩存刷新。
值可以不與主存同步嗎?這也是可能的嗎?
是的。
為什么會(huì)出現(xiàn)這種情況呢?
一般來說,緩存被刷新是有原因的。發(fā)生之前關(guān)系指示可能需要緩存刷新的位置。
當(dāng)只有一個(gè) cpu 核心和一個(gè) cpu 緩存時(shí),這種內(nèi)存可見性是否也會(huì)發(fā)生,還是總是發(fā)生?
如果只有一個(gè)核心,則緩存刷新不是問題1。
盡管我了解競(jìng)爭(zhēng)條件和死鎖,但我在理解內(nèi)存可見性問題時(shí)遇到了一些困難。這是架構(gòu)特定的東西嗎?
是和不是。內(nèi)存可見性可能會(huì)根據(jù)硬件架構(gòu)的不同而有所不同,但編寫代碼以提供明確定義的行為的方式是獨(dú)立于架構(gòu)的。
如果您確實(shí)需要深入了解內(nèi)存可見性問題,則需要了解內(nèi)存模型。Goetz 等人的第 16 章中以通俗易懂的方式對(duì)其進(jìn)行了描述,并在 JLS 中進(jìn)行了詳細(xì)說明。
我想知道為什么
Thread.yield()
調(diào)用不會(huì)屈服于主線程,然后主線程應(yīng)該刷新到主內(nèi)存
可能
Thread.yield()
會(huì)屈服于另一個(gè)可運(yùn)行的線程。然而,當(dāng)yield()
調(diào)用時(shí),線程很可能main
不再可運(yùn)行。(或者它可能仍在運(yùn)行。)不會(huì) 在主線程和子線程中的任何語句之間
yield()
創(chuàng)建發(fā)生之前。如果沒有發(fā)生之前關(guān)系,運(yùn)行時(shí)就沒有義務(wù)確保主線程分配的結(jié)果對(duì)子線程可見。雖然
Thread.yield()
可能會(huì)執(zhí)行緩存刷新2,但它將刷新子線程的緩存,而不是父線程的緩存。
因此,子線程的循環(huán)可能會(huì)無限期地繼續(xù)下去。
1 - 實(shí)際上,這可能過于簡(jiǎn)單化了。例如,在一個(gè)具有一個(gè)核心和多個(gè)具有自己的緩存的超線程的系統(tǒng)中,將需要緩存刷新。
2 - 例如,如果yield()
確實(shí)導(dǎo)致上下文切換,則上下文切換通常包括緩存刷新,作為操作系統(tǒng)執(zhí)行的線程狀態(tài)保存的一部分。但是,yield()
不一定會(huì)導(dǎo)致上下文切換。此外,JLS 并沒有規(guī)定這方面。

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超6個(gè)贊
字段可見性意味著線程觀察者字段值來自高速緩存,并且可以具有與 CPU 另一個(gè)核心中的其他高速緩存不同的狀態(tài)。JVM 不保證訪問共享資源的不同線程的字段可見性,程序員需要使用 synchronized 來防止讀取不正確的狀態(tài),或使用 volatile 來保證更改被刷新到其他緩存。
添加回答
舉報(bào)