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

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

如何解決Java中的“雙重檢查鎖定已損壞”聲明?

如何解決Java中的“雙重檢查鎖定已損壞”聲明?

慕哥9229398 2019-11-13 09:36:34
我想為Java中的多線程實(shí)現(xiàn)延遲初始化。我有一些這樣的代碼:class Foo {    private Helper helper = null;    public Helper getHelper() {        if (helper == null) {            Helper h;            synchronized(this) {                h = helper;                if (h == null)                     synchronized (this) {                        h = new Helper();                    } // release inner synchronization lock                helper = h;            }         }            return helper;    }    // other functions and members...}我得到了“雙重檢查鎖定已損壞”聲明。我該如何解決?
查看完整描述

3 回答

?
www說

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

以下是第71項(xiàng)中建議的慣用語:明智地使用 Effective Java:


如果您需要使用延遲初始化來提高實(shí)例字段的性能,請(qǐng)使用double-check idiom。這種習(xí)慣用法避免了在初始化字段后訪問字段時(shí)發(fā)生鎖定的費(fèi)用(項(xiàng)67)。習(xí)慣用語的想法是檢查字段的值兩次(因此,將其命名為double-check):一次不鎖定,然后,如果該字段似乎未初始化,則第二次鎖定。僅當(dāng)?shù)诙螜z查表明該字段未初始化時(shí),該調(diào)用才會(huì)初始化該字段。因?yàn)槿绻撟侄我呀?jīng)初始化就沒有鎖定,所以聲明該字段至關(guān)重要volatile(項(xiàng)目66)。這是成語:


// Double-check idiom for lazy initialization of instance fields

private volatile FieldType field;


private FieldType getField() {

    FieldType result = field;

    if (result != null) // First check (no locking)

        return result;

    synchronized(this) {

        if (field == null) // Second check (with locking)

            field = computeFieldValue();

        return field;

    }

}

該代碼可能看起來有些混亂。特別是,對(duì)局部變量結(jié)果的需求可能不清楚。該變量的作用是確保在已初始化字段的常見情況下,該字段僅被讀取一次。盡管不是絕對(duì)必要的,但是這可以提高性能,并且通過應(yīng)用于低級(jí)并發(fā)編程的標(biāo)準(zhǔn)可以更加優(yōu)雅。在我的機(jī)器上,上述方法比不帶局部變量的明顯方法快25%。


在1.5版之前,由于volatile修飾符的語義不足以支持它,所以雙重檢查慣用語不能可靠地工作[Pugh01]。版本1.5中引入的內(nèi)存模型解決了此問題[JLS,17,Goetz06 16]。如今,仔細(xì)檢查慣用語是延遲初始化實(shí)例字段的首選技術(shù)。雖然您也可以將雙重檢查慣用語應(yīng)用于靜態(tài)字段,但沒有理由這樣做:惰性初始化持有人類慣用語是更好的選擇。


參考

有效的Java,第二版

項(xiàng)目71:明智地使用惰性初始化


查看完整回答
反對(duì) 回復(fù) 2019-11-13
?
眼眸繁星

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

使用ThreadLocal的DCL作者:Brian Goetz @ JavaWorld


DCL有什么問題?


DCL依賴于資源字段的不同步使用。這似乎無害,但事實(shí)并非如此。要了解為什么,請(qǐng)想象線程A在同步塊內(nèi)部,執(zhí)行語句resource = new Resource();。而線程B剛剛進(jìn)入getResource()??紤]此初始化對(duì)內(nèi)存的影響。新資源對(duì)象的內(nèi)存將被分配;Resource的構(gòu)造函數(shù)將被調(diào)用,初始化新對(duì)象的成員字段;并且SomeClass的字段資源將被分配一個(gè)對(duì)新創(chuàng)建對(duì)象的引用。


class SomeClass {

  private Resource resource = null;

  public Resource getResource() {

    if (resource == null) {

      synchronized {

        if (resource == null) 

          resource = new Resource();

      }

    }

    return resource;

  }

}

但是,由于線程B不在同步塊內(nèi)執(zhí)行,因此它們看到這些內(nèi)存操作的順序可能與一個(gè)線程A的執(zhí)行順序不同。B可能會(huì)按照以下順序看到這些事件(并且編譯器還可以自由地重新排列這樣的指令):分配內(nèi)存,分配對(duì)資源的引用,調(diào)用構(gòu)造函數(shù)。假設(shè)線程B在分配了內(nèi)存并設(shè)置了資源字段之后但在調(diào)用構(gòu)造函數(shù)之前出現(xiàn)。它看到資源不為空,跳過同步塊,并返回對(duì)部分構(gòu)造的Resource的引用!不用說,結(jié)果既不是預(yù)期的也不是期望的。


ThreadLocal可以幫助修復(fù)DCL嗎?


我們可以使用ThreadLocal來實(shí)現(xiàn)DCL習(xí)慣用法的明確目標(biāo)-延遲初始化,而無需在公共代碼路徑上進(jìn)行同步??紤]以下(線程安全)DCL版本:


清單2.使用ThreadLocal的DCL


class ThreadLocalDCL {

  private static ThreadLocal initHolder = new ThreadLocal();

  private static Resource resource = null;

  public Resource getResource() {

    if (initHolder.get() == null) {

      synchronized {

        if (resource == null) 

          resource = new Resource();

        initHolder.set(Boolean.TRUE);

      }

    }

    return resource;

  }

}

我認(rèn)為; 這里每個(gè)線程將一次進(jìn)入SYNC塊以更新threadLocal值;那么它不會(huì)。因此,ThreadLocal DCL將確保線程僅在SYNC塊內(nèi)進(jìn)入一次。


同步到底是什么意思?


Java將每個(gè)線程視為在其具有自己的本地內(nèi)存的處理器上運(yùn)行,每個(gè)線程都與共享的主內(nèi)存通信并與之同步。即使在單處理器系統(tǒng)上,由于內(nèi)存高速緩存的影響以及使用處理器寄存器存儲(chǔ)變量的影響,該模型還是有意義的。當(dāng)線程修改其本地內(nèi)存中的位置時(shí),該修改最終還將顯示在主內(nèi)存中,并且JMM定義了JVM必須何時(shí)在本地和主內(nèi)存之間傳輸數(shù)據(jù)的規(guī)則。Java架構(gòu)師意識(shí)到,過于嚴(yán)格的內(nèi)存模型會(huì)嚴(yán)重破壞程序性能。他們?cè)噲D設(shè)計(jì)一種內(nèi)存模型,該內(nèi)存模型將使程序在現(xiàn)代計(jì)算機(jī)硬件上運(yùn)行良好,同時(shí)仍提供保證,以允許線程以可預(yù)測的方式進(jìn)行交互。


Java可預(yù)測地呈現(xiàn)線程之間的交互的主要工具是synced關(guān)鍵字。許多程序員在強(qiáng)制執(zhí)行互斥信號(hào)量(mutex)時(shí)嚴(yán)格考慮同步,以防止一次由多個(gè)線程執(zhí)行關(guān)鍵部分。不幸的是,這種直覺不能完全描述同步的含義。


同步的語義確實(shí)的確包括基于信號(hào)量狀態(tài)的相互排斥執(zhí)行,但是它們還包括有關(guān)同步線程與主內(nèi)存交互的規(guī)則。特別是,獲取或釋放鎖會(huì)觸發(fā)內(nèi)存屏障,即線程的本地內(nèi)存和主內(nèi)存之間的強(qiáng)制同步。(某些處理器(例如Alpha)具有用于執(zhí)行內(nèi)存屏障的顯式機(jī)器指令。)當(dāng)線程退出同步塊時(shí),它將執(zhí)行寫屏障-在釋放之前,必須將在該塊中修改的所有變量清除到主內(nèi)存中鎖。同樣,進(jìn)入同步塊時(shí),它執(zhí)行讀取屏障操作-好像本地存儲(chǔ)器已失效,并且它必須從主存儲(chǔ)器中獲取將在該塊中引用的所有變量。


查看完整回答
反對(duì) 回復(fù) 2019-11-13
  • 3 回答
  • 0 關(guān)注
  • 431 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號(hào)

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