單例模式雙重校驗(yàn)寫法及延伸

最近看一些Java內(nèi)存模型方面的書沼瘫,講了一下Java的對(duì)象的內(nèi)存分配過(guò)程,其中有個(gè)例子講解多線程鎖的問(wèn)題,說(shuō)了下面的例子:

單例寫法 雙重校驗(yàn)寫法

//------------------------雙重校驗(yàn)鎖------------------
    private static Singleton singleton2;//-------1

    public static Singleton getInstance4() {//------------2
        if (singleton2 == null) {//-----------------------3
            synchronized (Singleton.class) {//------------4
                if (singleton2 == null)//-----------------5
                    singleton2 = new Singleton();//-------6
            }
        }
        return singleton;
    }

問(wèn)題處在了第6步粤策,Java創(chuàng)建對(duì)象的第6步可以分為以下三步:

memory = allocate();//----1
ctorInstance(memory);//-2
instance = memory;//-----3

其中2,3步在JVM編譯優(yōu)化時(shí)可能發(fā)生重排序误窖,這和采用的JIT有關(guān)叮盘,并且該重排序遵循intra-thread semantics法則(重排序后不會(huì)影響單線程的執(zhí)行結(jié)果)。

如果發(fā)生重排序霹俺,第3步先于第2步執(zhí)行柔吼,那么A線程可能只是讓對(duì)象指向內(nèi)存地址,并沒(méi)有實(shí)質(zhì)的初始化對(duì)象丙唧,那么線程B調(diào)用時(shí)就會(huì)發(fā)生錯(cuò)誤愈魏。

解決方案

  • 采用volatile

在Java1.5以后,volatile關(guān)鍵字被加強(qiáng)想际,這種重排序不允許在多線程中發(fā)生培漏。
即在對(duì)象聲明加上volatile關(guān)鍵字。
實(shí)質(zhì):禁止編譯的重排序胡本。

  • 采用JVM初始化類時(shí)加鎖

JVM的類的初始化階段牌柄,會(huì)獲取鎖,該鎖可以同步多線程對(duì)一個(gè)類的初始化侧甫。
此時(shí)衍生一種稱為:Initialization On Demand Holder idiom的解決方案珊佣。

    //-----------------------------靜態(tài)內(nèi)部類---------------
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance3() {
        return SingletonHolder.INSTANCE;
    }
JVM在多線程中初始化對(duì)象過(guò)程.jpg

** 實(shí)質(zhì): **利用JVM的多線程初始化對(duì)象的特性蹋宦,允許重排序,但對(duì)其他線程不可見(jiàn)咒锻。

另外根據(jù)Java語(yǔ)言規(guī)范冷冗,一個(gè)類在一下5種情況會(huì)發(fā)生初始化:
  • T是一個(gè)類,并且T的實(shí)例被創(chuàng)建虫碉。
  • T是一個(gè)類贾惦,且T中的靜態(tài)方法被調(diào)用
  • T是一個(gè)類,且T中的一個(gè)靜態(tài)字段被賦值敦捧。
  • T是一個(gè)類须板,且T中的非常量字段被使用
  • T是一個(gè)頂級(jí)類(TOP Level Class),有斷言語(yǔ)句嵌套在T內(nèi)部被執(zhí)行兢卵。(assert語(yǔ)句习瑰,很少用改規(guī)則)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市秽荤,隨后出現(xiàn)的幾起案子甜奄,更是在濱河造成了極大的恐慌,老刑警劉巖窃款,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件课兄,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡晨继,警方通過(guò)查閱死者的電腦和手機(jī)烟阐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)紊扬,“玉大人蜒茄,你說(shuō)我怎么就攤上這事〔褪海” “怎么了檀葛?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)腹缩。 經(jīng)常有香客問(wèn)我屿聋,道長(zhǎng),這世上最難降的妖魔是什么藏鹊? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任胜臊,我火速辦了婚禮,結(jié)果婚禮上伙判,老公的妹妹穿的比我還像新娘。我一直安慰自己黑忱,他們只是感情好宴抚,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布勒魔。 她就那樣靜靜地躺著,像睡著了一般菇曲。 火紅的嫁衣襯著肌膚如雪冠绢。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天常潮,我揣著相機(jī)與錄音弟胀,去河邊找鬼。 笑死喊式,一個(gè)胖子當(dāng)著我的面吹牛孵户,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岔留,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼夏哭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了献联?” 一聲冷哼從身側(cè)響起竖配,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎里逆,沒(méi)想到半個(gè)月后进胯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡原押,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年胁镐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片班眯。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡希停,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出署隘,到底是詐尸還是另有隱情宠能,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布磁餐,位于F島的核電站违崇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏诊霹。R本人自食惡果不足惜羞延,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脾还。 院中可真熱鬧伴箩,春花似錦、人聲如沸鄙漏。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至巩步,卻和暖如春旁赊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背椅野。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工终畅, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人竟闪。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓离福,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親瘫怜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子术徊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容