久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

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

 chenge 2006-04-14

Singleton可能是所有設(shè)計(jì)模式中最簡單的設(shè)計(jì)模式啦,。它是如此的簡單,,以至于當(dāng)我們看著它的UML圖的時候會為終于沒有了惱人的連線而雀躍,,我們也不用去記憶并體會它有多么強(qiáng)大的功能,、多么高深的實(shí)現(xiàn)技巧,。使用它的理由只有一個――得到一個Class的唯一的Object,。它的實(shí)現(xiàn)是如此簡單,,以至于你會怪我把它的Code列在下面是在浪費(fèi)服務(wù)器空間。但是,,天下并沒有這么爽的事兒,,當(dāng)Singleton遇到multi-threading,一些不為人所知的陷阱悄悄的浮上了水面,,我們不得不小心應(yīng)對它們,。一下的示例以Java作為編程語言,討論了multi-threading下實(shí)現(xiàn) Singleton的策略,,并順便告訴你幾個關(guān)于Java實(shí)現(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的實(shí)現(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á)成了一致,,這確實(shí)是個大問題,。我們怎么解決它?“我們可以用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會在所有線程之前先實(shí)例化一個Object,所有的getInstance()調(diào)用都是在引用這個預(yù)先產(chǎn)生的Object,,不會有任何的問題啦~

但是,,完美主義的我們并不滿意:“無論是否使用這個Class,都會預(yù)先產(chǎn)生一個Object,,這很不優(yōu)雅,!”那我們就看看優(yōu)雅的解決方案??紤]一下 multi-threading下出現(xiàn)錯誤的原因,,并不是因?yà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可以被同時運(yùn)行的若干個線程正確的修改,而getInstance()方法體中的寫法則保證了細(xì)力度的線程鎖,。注意,,uniqueInstance == null被判斷了兩次,這是必要的,,這種方法叫做Double-checked locking,。

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

  • Double-checked locking最好只在Java 5中使用。在Java 1.4以及之前版本的諸多實(shí)現(xiàn)中,,volatile關(guān)鍵字都被錯誤的實(shí)現(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è)計(jì)Class Loader時,最好在獲取Object的時候同時指定它的Class Loader,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多