溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

java雙重檢驗(yàn)鎖模式是什么

發(fā)布時(shí)間:2022-03-22 17:05:40 來(lái)源:億速云 閱讀:146 作者:iii 欄目:大數(shù)據(jù)

這篇“java雙重檢驗(yàn)鎖模式是什么”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“java雙重檢驗(yàn)鎖模式是什么”文章吧。 

起因

在對(duì)項(xiàng)目進(jìn)行PMD靜態(tài)代碼檢測(cè)時(shí),遇到了這樣一個(gè)問題

Partially created objects can be returned by the Double Checked Locking pattern when used in Java. An optimizing JRE may assign a reference to the baz variable before it calls the constructor of the object the reference points to.

Note: With Java 5, you can make Double checked locking work, if you declare the variable to be volatile.

大概意思是,使用雙重檢驗(yàn)鎖模式,可能會(huì)返回一個(gè)部分初始化的對(duì)象??赡艽蠹矣行┮蓱],什么是部分初始化的對(duì)象,我們下面繼續(xù)分析 

什么是雙重檢驗(yàn)鎖模式

public static Singleton getSingleton() {
    if (instance == null) {                        
        synchronized (Singleton.class) {
            if (instance == null) {                 
                instance = new Singleton();
            }
        }
    }
    return instance ;
}
 

我們看到,在同步代碼塊的內(nèi)部和外部都判斷了instance == null,這是因?yàn)?,可能?huì)有多個(gè)線程同時(shí)進(jìn)入到同步代碼塊外的if判斷中,如果在同步代碼塊內(nèi)部不進(jìn)行判空的話,可能會(huì)初始化多個(gè)實(shí)例。 

問題所在

這種寫法看似完美無(wú)缺,但它卻是有問題的,或者說(shuō)它并不擔(dān)保一定完美無(wú)缺。主要原因在于instance = new Singleton();并不是原子性的操作。
創(chuàng)建一個(gè)對(duì)象可以分為三部:

1.分配對(duì)象的內(nèi)存空間
2.初始化對(duì)象
3.設(shè)置instance指向剛分配的內(nèi)存地址
當(dāng)instance指向分配地址時(shí),instance是不為null的
 

但是,2、3步之間,可能會(huì)被重排序,造成創(chuàng)建對(duì)象順序變?yōu)?-3-2.試想一個(gè)場(chǎng)景:
線程A第一次創(chuàng)建對(duì)象Singleton,對(duì)象創(chuàng)建順序?yàn)?-3-2;
當(dāng)給instance分配完內(nèi)存后,這時(shí)來(lái)了一個(gè)線程B調(diào)用了getSingleton()方法
這時(shí)候進(jìn)行instance == null的判斷,發(fā)現(xiàn)instance并不為null。
但注意這時(shí)候instance并沒有初始化對(duì)象,線程B則會(huì)將這個(gè)未初始化完成的對(duì)象返回。那B線程使用instance時(shí)就可能會(huì)出現(xiàn)問題,這就是雙重檢查鎖問題所在。 

使用volatile

對(duì)于上述的問題,我們可以通過(guò)把instance聲明為volatile型來(lái)解決

public class Singleton{
    private volatile static Singleton instance;
    public static Singleton getSingleton() {
        if (instance == null) {                        
            synchronized (Singleton.class) {
                if (instance == null) {                 
                    instance = new Singleton();
                }
            }
        }
        return instance ;
    }
}
 

但是必須在JDK5版本以上使用。 

靜態(tài)內(nèi)部類

public class Singleton {  
    private static class SingletonHolder {  
        private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE; 
    }  
}

這種寫法是目前比較推薦的一種寫法,采用靜態(tài)內(nèi)部類的方式,既實(shí)現(xiàn)了懶加載又不會(huì)出現(xiàn)線程安全問題。而且減少了synchronized的開銷。

以上就是關(guān)于“java雙重檢驗(yàn)鎖模式是什么”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI