第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

需要幫助理解 java 中多線程時(shí)的內(nèi)存可見性問題

需要幫助理解 java 中多線程時(shí)的內(nèi)存可見性問題

波斯汪 2023-09-13 10:21:36
我正在實(shí)踐 Goetze 的 Java 并發(fā)性,并且在不使用同步關(guān)鍵字時(shí)停留在共享變量的內(nèi)存可見性部分。代碼如下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;    }}作者說這個(gè)類可能會(huì)永遠(yuǎn)循環(huán),因?yàn)閞eady的值可能永遠(yuǎn)不會(huì)對(duì)讀者線程可見。我不明白這個(gè)說法。我的看法是,首先主線程啟動(dòng)并將數(shù)字和準(zhǔn)備設(shè)置為 true。但是另一個(gè)線程有自己的堆棧以及自己的 number 和 read 值,這些值不與主內(nèi)存同步,并且這兩個(gè)線程只有自己的變量副本。現(xiàn)在,讀者線程應(yīng)該永遠(yuǎn)保持在循環(huán)中。我想知道為什么該Thread.yield變量不會(huì)屈服于主線程,然后主線程應(yīng)該刷新到主內(nèi)存,然后讀取線程應(yīng)該拾取這個(gè)新值并終止循環(huán)并打印正確的值,因?yàn)檫@也應(yīng)該是已同步。所以我想我有一些問題。CPU 緩存中的值多久與主內(nèi)存刷新/同步一次?值可以不與主存同步嗎?這也是可能的嗎?為什么會(huì)出現(xiàn)這種情況呢?當(dāng)只有一個(gè) cpu 核心和一個(gè) cpu 緩存時(shí),這種內(nèi)存可見性是否也會(huì)發(fā)生,還是總是發(fā)生?盡管我了解競(jìng)爭(zhēng)條件和死鎖,但我在理解內(nèi)存可見性問題時(shí)遇到了一些困難。這是架構(gòu)特定的東西嗎?
查看完整描述

2 回答

?
慕村225694

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)存

  1. 可能Thread.yield() 會(huì)屈服于另一個(gè)可運(yùn)行的線程。然而,當(dāng)yield()調(diào)用時(shí),線程很可能main不再可運(yùn)行。(或者它可能仍在運(yùn)行。)

  2. 不會(huì) 在主線程和子線程中的任何語句之間yield()創(chuàng)建發(fā)生之前。如果沒有發(fā)生之前關(guān)系,運(yùn)行時(shí)就沒有義務(wù)確保主線程分配的結(jié)果對(duì)子線程可見。

  3. 雖然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ī)定這方面。


查看完整回答
反對(duì) 回復(fù) 2023-09-13
?
慕妹3242003

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超6個(gè)贊

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



查看完整回答
反對(duì) 回復(fù) 2023-09-13
  • 2 回答
  • 0 關(guān)注
  • 120 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)