2 回答

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

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