成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

淺談雙重檢查鎖定和延遲初始化

Shonim / 1256人閱讀

摘要:非線程安全的雙重檢查鎖這里看起來很完美,但是是一個(gè)錯(cuò)誤的優(yōu)化,代碼在讀取到不為的時(shí)候,引用的對象有可能換沒有完成初始化,這樣返回的是有問題的。

在Java多線程程序中,有時(shí)需要采用延遲初始化來降低初始化類和創(chuàng)建對象的開銷,雙重檢查鎖定是常見的延遲初始化技術(shù),但它是一種錯(cuò)誤的用法

雙重檢查鎖的演進(jìn)以及問題

使用syncronized實(shí)現(xiàn)

public synchronized static Instance getInstance() {
    if (instance == null) {
        instance = new Instance();
    }
    return instance;
}

多線程情況下性能開銷比較大。

非線程安全的雙重檢查鎖

public static Instance getInstance2() {
    if (instance2 == null) {
        synchronized (UnsafeLazyInitialization.class) {
            if (instance2 == null) {
                instance2 = new Instance();
            }
        }
    }
    return instance2;
}

這里看起來很完美,但是是一個(gè)錯(cuò)誤的優(yōu)化,代碼在讀取到instance2不為null的時(shí)候,instance引用的對象有可能換沒有完成初始化,這樣返回的instance2是有問題的。
出現(xiàn)這個(gè)問題的根源在什么地方?
instance2 = new Instance();這一行代碼在處理器執(zhí)行的時(shí)候有三部操作:
1、memory = allocate() //分配內(nèi)存
2、ctorInstance(memory) //初始化對象
3、instance = memory //設(shè)置instance指向剛剛分配的內(nèi)存地址

上面的三行代碼中,2和3之間可能會(huì)被指令重排序。如果重排序之后的順序?yàn)?,3,2.線程A執(zhí)行2的時(shí)候,線程A判斷instance2不為空,返回的instance2對象就是一個(gè)還未初始化的對象。

所以對于上面的解決思路有兩種:
1、不允許2和3進(jìn)行指令的重排序
3、允許2和3重排序,但是不允許其他線程看到這個(gè)重排序。

不允許2和3進(jìn)行指令重排序(線程安全的雙重檢查鎖)

/**聲明為volatile之后,2和3的指令重排序會(huì)被禁止*/
public static volatile Instance instance3;
public static Instance getInstance3() {
    if (instance3 == null) {
        synchronized (UnsafeLazyInitialization.class) {
            if (instance3 == null) {
                instance3 = new Instance();
            }
        }
    }
    return instance3;
}

-基于類初始化的解決

public class InstanceFactory {
    
    private static class InstanceHolder {
        public static Instance instance = new Instance();
    }

    public static Instance getInstance () {
        return InstanceHolder.instance;
    }
}

這個(gè)是基于JVM的特性:JVM在類初始化的時(shí)候,會(huì)執(zhí)行類初始化,在執(zhí)行類初始化期間,JVM會(huì)獲取一把鎖,這個(gè)鎖可以同步多個(gè)線程對同一個(gè)類的初始化。初始化一個(gè)類,包括執(zhí)行這個(gè)類的靜態(tài)初始化和初始化這個(gè)類中的靜態(tài)字段。根據(jù)Java語言規(guī)范,在首次發(fā)生下面的任何一種情況,一個(gè)類或接口類型將立即被初始化。
1)T的實(shí)例類型被創(chuàng)建
2)T是一個(gè)類, 且T中的靜態(tài)方法被調(diào)用
3)T聲明的一個(gè)靜態(tài)字段被賦值
4)T聲明的靜態(tài)字段被使用

在這里,首次執(zhí)行g(shù)etInstance(),那么InstanceHolder會(huì)進(jìn)行初始化。

任何的線程安全操作在底層都是對應(yīng)指令重排序以及內(nèi)存可見性的問題。操作系統(tǒng)才是根本啊~~

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/74943.html

相關(guān)文章

  • 雙重檢查鎖定延遲始化

    摘要:基于的雙重檢查鎖定的解決方案對于前面的基于雙重檢查鎖定來實(shí)現(xiàn)延遲初始化的方案指示例代碼,我們只需要做一點(diǎn)小的修改把聲明為型,就可以實(shí)現(xiàn)線程安全的延遲初始化。 雙重檢查鎖定的由來 在java程序中,有時(shí)候可能需要推遲一些高開銷的對象初始化操作,并且只有在使用這些對象時(shí)才進(jìn)行初始化。此時(shí)程序員可能會(huì)采用延遲初始化。但要正確實(shí)現(xiàn)線程安全的延遲初始化需要一些技巧,否則很容易出現(xiàn)問題。比如,下...

    yvonne 評論0 收藏0
  • 為什么雙重檢查鎖模式需要 volatile ?

    摘要:注意,禁止指令重排序在之后才被修復(fù)使用局部變量優(yōu)化性能重新查看中雙重檢查鎖定代碼。幫助文檔雙重檢查鎖定與延遲初始化有關(guān)雙重檢查鎖定失效的說明 雙重檢查鎖定(Double check locked)模式經(jīng)常會(huì)出現(xiàn)在一些框架源碼中,目的是為了延遲初始化變量。這個(gè)模式還可以用來創(chuàng)建單例。下面來看一個(gè) Spring 中雙重檢查鎖定的例子。 showImg(https://segmentfaul...

    geekzhou 評論0 收藏0
  • 單例模式總結(jié)

    摘要:如果是后者,則在執(zhí)行完畢未執(zhí)行之前,被線程二搶占了,這時(shí)已經(jīng)是非了但卻沒有初始化,所以線程二會(huì)直接返回在之后雙重檢查鎖定才能夠正常達(dá)到單例效果,之前有個(gè)坑。所以,在版本前,雙重檢查鎖形式的單例模式是無法保證線程安全的。 第一種(懶漢, 線程不安全): public class Singleton { private static Singleton instance; ...

    xorpay 評論0 收藏0
  • 雙重檢查鎖定失效分析

    摘要:雙重檢查鎖定以下稱為已被廣泛當(dāng)做多線程環(huán)境下延遲初始化的一種高效手段。由于沒有對這些做出明確規(guī)定,很難說是否有效??梢栽谥惺褂蔑@式的內(nèi)存屏障來使生效,但中并沒有這些屏障。如果改變鎖釋放的語義釋放時(shí)執(zhí)行一個(gè)雙向的內(nèi)存屏障將會(huì)帶來性能損失。 雙重檢查鎖定(以下稱為DCL)已被廣泛當(dāng)做多線程環(huán)境下延遲初始化的一種高效手段。 showImg(http://segmentfault.com/i...

    keke 評論0 收藏0
  • 單例模式與雙重檢查鎖定(double-checked locking)

    摘要:對于而言,它執(zhí)行的是一個(gè)個(gè)指令。在指令中創(chuàng)建對象和賦值操作是分開進(jìn)行的,也就是說語句是分兩步執(zhí)行的。此時(shí)線程打算使用實(shí)例,卻發(fā)現(xiàn)它沒有被初始化,于是錯(cuò)誤發(fā)生了。 1.餓漢式單例 public class Singleton { private static Singleton instance = new Singleton(); ...

    yearsj 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<