国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
博客園 - Allen Young - 當(dāng)Singleton遇到multi-threading

Singleton可能是所有設(shè)計模式中最簡單的設(shè)計模式啦。它是如此的簡單,以至于當(dāng)我們看著它的UML圖的時候會為終于沒有了惱人的連線而雀躍,我們也不用去記憶并體會它有多么強(qiáng)大的功能、多么高深的實現(xiàn)技巧。使用它的理由只有一個――得到一個Class的唯一的Object。它的實現(xiàn)是如此簡單,以至于你會怪我把它的Code列在下面是在浪費服務(wù)器空間。但是,天下并沒有這么爽的事兒,當(dāng)Singleton遇到multi-threading,一些不為人所知的陷阱悄悄的浮上了水面,我們不得不小心應(yīng)對它們。一下的示例以Java作為編程語言,討論了multi-threading下實現(xiàn) Singleton的策略,并順便告訴你幾個關(guān)于Java實現(xiàn)Singleton的、你可能不知道的tricky things。

public class Singleton {

    
private static Singleton uniqueInstance;
    
    
private Singleton() {}
    
    
public static Singleton getInstance(){
        
if(uniqueInstance == null){
            uniqueInstance 
= new Singleton();
        }
        
return uniqueInstance;
    }
}

這是典型的Singleton的實現(xiàn),在single-threading下,它沒有任何問題。但是,你能告訴我在multi-threading下,可能會發(fā)生什么事情么?multi-threading是頑皮的小孩,它不保證各個線程執(zhí)行的順序,所以,會有一種可能,if (uniqueInstance == null)這個判斷會在不同的線程中連續(xù)執(zhí)行。讓我們看看最簡單的、只有兩個線程的情況:
thread 1                             thread 2                             uniqueInstance
if(uniqueInstance == null)                                                null
                                     if(uniqueInstance == null)           null
uniqueInstance = new Singleton();                                         new object
                                     uniqueInstance = new Singleton();    new object

看到了么?產(chǎn)生了兩個不同的Object!這不一定永遠(yuǎn)是壞事,比如這是一個在線購物的控制系統(tǒng),那么你可能會用一件衣服的錢買到兩件衣服,雖然也有可能是你付了錢,但是沒得到衣服,但是概率是50%對50%的,也不是什么大不了的事兒~但是,如果這是一個鐵路調(diào)度控制系統(tǒng)呢?火車也許會相撞。如果這是一個核反應(yīng)堆的控制系統(tǒng)呢?一個城市可能就變成廢墟了(當(dāng)然,也許你希望這發(fā)生在日本)。

OK!我們達(dá)成了一致,這確實是個大問題。我們怎么解決它?“我們可以用synchronized!”有人興奮的叫到:“真是個好主意!”好,我們來試試看~
public class Singleton {

    
private static Singleton uniqueInstance;
    
    
private Singleton() {}
    
    
public static synchronized Singleton getInstance(){
        
if(uniqueInstance == null){
            uniqueInstance 
= new Singleton();
        }
        
return uniqueInstance;
    }
}
好樣的!現(xiàn)在同一時刻只有一個線程能調(diào)用getInstance()方法,不會存在城市被炸平的悲劇了,我們拯救了幾百萬人(上海的話,一千多萬人)!我代表他們感謝你,但是,過不了多久就有人會站出來抱怨:“為什么系統(tǒng)的速度變慢了?”這些沒良心的人們,這么快就忘記了這段code拯救了他們的性命,竟然抱怨起了這么小的問題!憤憤之余,你開始思考速度變慢的原因。

啊,synchronized,它使得原本并行的訪問變成了串行,這是性能的瓶頸,有什么辦法可以解決嗎?當(dāng)然,有人站了出來:“我有投機(jī)取巧的方法?!?br>
public class Singleton {

    
private static Singleton uniqueInstance = new Singleton();

    
private Singleton() {}

    
public static Singleton getInstance() {
        
return uniqueInstance;
    }
}
問題解決了~JVM會在所有線程之前先實例化一個Object,所有的getInstance()調(diào)用都是在引用這個預(yù)先產(chǎn)生的Object,不會有任何的問題啦~

但是,完美主義的我們并不滿意:“無論是否使用這個Class,都會預(yù)先產(chǎn)生一個Object,這很不優(yōu)雅!”那我們就看看優(yōu)雅的解決方案。考慮一下 multi-threading下出現(xiàn)錯誤的原因,并不是因為不同的線程同時調(diào)用了getInstance()方法,而是if (uniqueInstance == null)出現(xiàn)了意想不到的排列,也就是說,只有在產(chǎn)生Object的時候,才會有multi-threading的問題,當(dāng) uniqueInstance != null時,多少個線程都不會有問題。因此,我們得到了結(jié)論:只需要對創(chuàng)建Object的code上鎖就可以了。
public class Singleton {

    
private volatile static Singleton uniqueInstance;

    
private Singleton() {}

    
public static Singleton getInstance() {
        
if (uniqueInstance == null) {
            
synchronized (Singleton.class) {
                
if (uniqueInstance == null) {
                    uniqueInstance = 
new Singleton();
                }
            }
        }
        
return uniqueInstance;
    }
}
關(guān)鍵字volatile可以保證uniqueInstance可以被同時運行的若干個線程正確的修改,而getInstance()方法體中的寫法則保證了細(xì)力度的線程鎖。注意,uniqueInstance == null被判斷了兩次,這是必要的,這種方法叫做Double-checked locking。

噹噹噹噹~任務(wù)完成,Singleton不在懼怕multi-threading啦!讓我們來看看關(guān)于Java實現(xiàn)Singleton的tricky things。

  • Double-checked locking最好只在Java 5中使用。在Java 1.4以及之前版本的諸多實現(xiàn)中,volatile關(guān)鍵字都被錯誤的實現(xiàn),這會導(dǎo)致Double-checked locking的不正確執(zhí)行。
  • 在Java 1.2以及之前的版本中,JVM的垃圾回收器存在一個bug:當(dāng)一個Singleton的Object不存在全局引用(即只有自身的instance變量 在引用這Object)的時候,垃圾回收器會回收這個Object。也就是說,在這種情況下,getIntance()會得到一個新的Object,這不會導(dǎo)致城市被炸平,但是會導(dǎo)致做了10年的核反應(yīng)成果突然消失,當(dāng)然不是我們想要的。
  • Java允許不同的Class Loader創(chuàng)建自己的Object,它們用namespace來區(qū)別這些Object。因此,當(dāng)你的Singleton設(shè)計Class Loader時,最好在獲取Object的時候同時指定它的Class Loader。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
java單例模式二
設(shè)計模式讀書筆記-----單例模式
深入靈魂的考驗,每行注釋都是靈魂的單例模式,源碼+實例降臨
面試被問設(shè)計模式?不要怕看這里:單例模式
算法55 Singleton(C/C++/C#)
C# 設(shè)計模式-單例模式
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服