單例模式雙重校驗(yàn)的再理解

提起單例模式,作為攻城獅的你我都不會(huì)感覺(jué)到陌生,而為了確保在程序中的線(xiàn)程安全,我們常常會(huì)傾向于雙重校驗(yàn)和靜態(tài)類(lèi)兩種方式。而且眾所周知,在雙重校驗(yàn)的方式中,我們發(fā)現(xiàn)了關(guān)鍵字volatile的身影,而且一直以來(lái)小編只是知道 該關(guān)鍵字可以保證操作之間的可見(jiàn)性。但是只知其一啊,今天突然明白這其中的道理:

public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
如上述代碼片所示,singleton變量使用了volatile關(guān)鍵字修飾,也就意味著這個(gè)變量對(duì)接下來(lái)的操作具有可見(jiàn)性(原因稍后會(huì)有解釋?zhuān)?br> ? 如果上述代碼中singleton變量去掉volatile關(guān)鍵字……

public class Singleton {
private static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
如上述代碼所示,如果是單線(xiàn)程操作,由于代碼的順序間接的決定了執(zhí)行順序,而且在單線(xiàn)程中,即使jvm執(zhí)行了順序重排,仍然不會(huì)出現(xiàn)問(wèn)題;

在討論多線(xiàn)程的場(chǎng)景之前,我們先來(lái)科普一下 對(duì)象初始化的過(guò)程:在對(duì)象初始化也就是如第八行代碼(singleton = new Singleton();  )所示,要知道,這行代碼一共有三個(gè)過(guò)程:

分配對(duì)象的內(nèi)存空間-->初始化對(duì)象 --> 將singleton指向剛分配好的內(nèi)存地址

-----------------------------------------我是分割線(xiàn)-------------------------------------------

明白初始化的過(guò)程之后,我們開(kāi)始討論多線(xiàn)程的場(chǎng)景:假設(shè)現(xiàn)在有線(xiàn)程A和線(xiàn)程B,當(dāng)兩個(gè)線(xiàn)程同時(shí)來(lái)訪(fǎng)問(wèn)Singleton對(duì)象,但是在訪(fǎng)問(wèn)期間會(huì)有以下不安全的情況:

1)A /B 線(xiàn)程同時(shí)訪(fǎng)問(wèn),這時(shí)兩個(gè)線(xiàn)程都發(fā)現(xiàn)singleton為空,所以?xún)蓚€(gè)線(xiàn)程都會(huì)創(chuàng)建一個(gè)singleton變量,這自然不符合單例模式的初衷……

2)在不同的時(shí)間,A、B線(xiàn)程分別來(lái)訪(fǎng)問(wèn)這個(gè)Singleton對(duì)象,可能會(huì)出現(xiàn)報(bào)錯(cuò)的情況:

        ![image.png](https://upload-images.jianshu.io/upload_images/4587933-bb1b30c485451510.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)


 如上圖所示,線(xiàn)程B在T4時(shí)間的訪(fǎng)問(wèn)一定會(huì)出現(xiàn)NullPointerException,因?yàn)檎也坏竭@個(gè)對(duì)象噻!

 關(guān)于volatile修飾之后,為什么就可以避免上圖中多線(xiàn)程訪(fǎng)問(wèn)的問(wèn)題,將在下篇中講解,敬請(qǐng)期待!

————————————————
版權(quán)聲明:本文為CSDN博主「楊士超」的原創(chuàng)文章,遵循CC 4.0 by-sa版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/YSC1123/article/details/77867138

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 設(shè)計(jì)模式中,最為基礎(chǔ)與常見(jiàn)的就是單例模式。這也是經(jīng)常在面試過(guò)程中被要求手寫(xiě)的設(shè)計(jì)模式。 下面就先寫(xiě)一個(gè)簡(jiǎn)單的單例:...
    樂(lè)百事52淑熙閱讀 1,849評(píng)論 0 0
  • 定義 一個(gè)類(lèi)只有一個(gè)實(shí)例,自行實(shí)例化并提供給整個(gè)系統(tǒng)。 基本思路 將該類(lèi)構(gòu)造函數(shù)私有化,并通過(guò)靜態(tài)方法獲取一個(gè)唯一...
    劇透下閱讀 304評(píng)論 0 0
  • 簡(jiǎn)介 單例模式是一種常用的軟件設(shè)計(jì)模式,其定義是單例對(duì)象的類(lèi)只能允許一個(gè)實(shí)例存在。許多時(shí)候整個(gè)系統(tǒng)只需要擁有一個(gè)的...
    上杉丶零閱讀 608評(píng)論 0 1
  • 一、稱(chēng)號(hào)沒(méi)想好。。。 最近幾百年飛升的是一位魔法師,他沒(méi)有魔法體質(zhì),卻有超高的魔法天賦。 兒時(shí)接受了一點(diǎn)冥想術(shù)的修...
    時(shí)光勿念閱讀 503評(píng)論 0 0
  • 一、父女第一次“吵架” 晚飯后我坐沙發(fā)上消食發(fā)呆,九九則在客廳里莫名地處于亢奮狀態(tài)——自編自演,手舞足蹈。這樣的“...
    山賊爺閱讀 532評(píng)論 2 2

友情鏈接更多精彩內(nèi)容