亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

需要幫助理解 java 中多線程時的內存可見性問題

需要幫助理解 java 中多線程時的內存可見性問題

波斯汪 2023-09-13 10:21:36
我正在實踐 Goetze 的 Java 并發性,并且在不使用同步關鍵字時停留在共享變量的內存可見性部分。代碼如下public class NoVisibility {    private static boolean ready;    private static int number;    private static class ReaderThread extends Thread {        public void run() {            while(!ready)                Thread.yield();            System.out.println(number);        }    }    public static void main(String[] args){        new ReaderThread().start();        number=42;        ready=true;    }}作者說這個類可能會永遠循環,因為ready的值可能永遠不會對讀者線程可見。我不明白這個說法。我的看法是,首先主線程啟動并將數字和準備設置為 true。但是另一個線程有自己的堆棧以及自己的 number 和 read 值,這些值不與主內存同步,并且這兩個線程只有自己的變量副本?,F在,讀者線程應該永遠保持在循環中。我想知道為什么該Thread.yield變量不會屈服于主線程,然后主線程應該刷新到主內存,然后讀取線程應該拾取這個新值并終止循環并打印正確的值,因為這也應該是已同步。所以我想我有一些問題。CPU 緩存中的值多久與主內存刷新/同步一次?值可以不與主存同步嗎?這也是可能的嗎?為什么會出現這種情況呢?當只有一個 cpu 核心和一個 cpu 緩存時,這種內存可見性是否也會發生,還是總是發生?盡管我了解競爭條件和死鎖,但我在理解內存可見性問題時遇到了一些困難。這是架構特定的東西嗎?
查看完整描述

2 回答

?
慕村225694

TA貢獻1880條經驗 獲得超4個贊

CPU 緩存中的值多久與主內存刷新/同步一次?

不明確的。當 JLS 中指定的可見性保證表明需要發生緩存刷新時,就會發生緩存刷新。

值可以不與主存同步嗎?這也是可能的嗎?

是的。

為什么會出現這種情況呢?

一般來說,緩存被刷新是有原因的。發生之前關系指示可能需要緩存刷新的位置。

當只有一個 cpu 核心和一個 cpu 緩存時,這種內存可見性是否也會發生,還是總是發生?

如果只有一個核心,則緩存刷新不是問題1。

盡管我了解競爭條件和死鎖,但我在理解內存可見性問題時遇到了一些困難。這是架構特定的東西嗎?

是和不是。內存可見性可能會根據硬件架構的不同而有所不同,但編寫代碼以提供明確定義的行為的方式是獨立于架構的。

如果您確實需要深入了解內存可見性問題,則需要了解內存模型。Goetz 等人的第 16 章中以通俗易懂的方式對其進行了描述,并在 JLS 中進行了詳細說明。


我想知道為什么Thread.yield()調用不會屈服于主線程,然后主線程應該刷新到主內存

  1. 可能Thread.yield() 屈服于另一個可運行的線程。然而,當yield()調用時,線程很可能main不再可運行。(或者它可能仍在運行。)

  2. 不會 在主線程和子線程中的任何語句之間yield()創建發生之前。如果沒有發生之前關系,運行時就沒有義務確保主線程分配的結果對子線程可見。

  3. 雖然Thread.yield() 可能會執行緩存刷新2,但它將刷新子線程的緩存,而不是父線程的緩存。

因此,子線程的循環可能會無限期地繼續下去。


1 - 實際上,這可能過于簡單化了。例如,在一個具有一個核心和多個具有自己的緩存的超線程的系統中,將需要緩存刷新。

2 - 例如,如果yield() 確實導致上下文切換,則上下文切換通常包括緩存刷新,作為操作系統執行的線程狀態保存的一部分。但是,yield()不一定會導致上下文切換。此外,JLS 并沒有規定這方面。


查看完整回答
反對 回復 2023-09-13
?
慕妹3242003

TA貢獻1824條經驗 獲得超6個贊

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



查看完整回答
反對 回復 2023-09-13
  • 2 回答
  • 0 關注
  • 112 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號