免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
單例在多線程下的問題: "懶漢"初始化的線程安全
單例的多線程線程安全問題的描述
通常的多線程的線程安全問題,往往被描述成"多線程共享線程實(shí)例變量"
但多線程下的實(shí)例變量如果是單例的話,本來就是該共享的,因?yàn)閱卫谕籎VM下只有一個(gè)
所以平常的線程安全問題,在這里正好相反,如果多線程不共享單例的實(shí)例變量,才是真正的線程安全問題
這也證明了線程安全的本質(zhì)是"實(shí)際值和理論值不符",而不能簡單的描述為"多線程共享線程實(shí)例變量就是線程安全問題"
自然,如果多線程共享單例,自然也共享單例的狀態(tài)


下面這樣的代碼,采用"懶漢"形式的初始化模式,在多線程下,可能會(huì)發(fā)生錯(cuò)誤
如果同時(shí)兩個(gè)線程訪問這個(gè)單例,一個(gè)發(fā)現(xiàn)為空,開始建立對象。但是同時(shí)在沒有建立完的時(shí)候,又一個(gè)線程進(jìn)來了,因?yàn)樯弦粋€(gè)線程沒有建立完實(shí)例,所以第二個(gè)實(shí)例仍能判斷為空。又建立了一個(gè)。就不是單例了,單例失敗
單例類
public class MySingleton2 {
    private static MySingleton2 instance;
    
    private MySingleton2(){}
    
    public static MySingleton2 getInstance() throws InterruptedException {
        if(instance==null){
            Thread.sleep(10000) // 為了展現(xiàn)出錯(cuò)誤,我們加了等待時(shí)間,以延長初始化的時(shí)間
            instance = new MySingleton2();
        }
        return instance;
    }
線程類
調(diào)用單例類
    public void run(){
        MySingleton2 mySingleton2=null;
        try {
            mySingleton2 = MySingleton2.getInstance();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(mySingleton2+":"+mySingleton2.hashCode());
    }
測試代碼:,起10個(gè)線程,都引用同一實(shí)例(單實(shí)例多線程)
        MyThread myThread= new MyThread();
        for(int i=0;i<10;i++){            
            Thread t = new Thread(myThread,String.valueOf(i));
            t.start();
            }
執(zhí)行結(jié)果: 看出現(xiàn)多個(gè)不同的單例類的實(shí)例,違反了單例的規(guī)范.
com.machome.singleton.MySingleton2@1270b73:19336051
com.machome.singleton.MySingleton2@60aeb0:6336176
com.machome.singleton.MySingleton2@16caf43:23899971
com.machome.singleton.MySingleton2@66848c:6718604
com.machome.singleton.MySingleton2@8813f2:8918002
com.machome.singleton.MySingleton2@1d58aae:30771886
com.machome.singleton.MySingleton2@83cc67:8637543
com.machome.singleton.MySingleton2@e09713:14718739
com.machome.singleton.MySingleton2@de6f34:14577460
com.machome.singleton.MySingleton2@156ee8e:22474382
所以這種"懶漢初始化"只能在單線程下使用


"懶漢初始化"解決:
  • 法1.用同步鎖保護(hù),但會(huì)造成性能低下。而且存在"二次檢查"的問題.
采用同步getInstance()方法
public synchronized static MySingleton3 getInstance() throws InterruptedException {
        if(instance==null){
                    Thread.sleep(10000);
                    instance = new MySingleton3();
        }
        return instance;
    }
執(zhí)行:問題解決,
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051

同步代碼塊
同步方法通常開銷很大,造成性能低下,因此建議采用同步代碼塊,但同步代碼塊存在"二次檢查"的問題
下面對初始化代碼塊加了同步
public static MySingleton3 getInstance() throws InterruptedException {
        if(instance==null){
            synchronized(MySingleton3.class){
                    Thread.sleep(10000);
                    instance = new MySingleton3();
            }
        }
執(zhí)行: 仍出現(xiàn)多個(gè)實(shí)例        
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@60aeb0:6336176
com.machome.singleton.MySingleton3@16caf43:23899971
com.machome.singleton.MySingleton3@66848c:6718604
com.machome.singleton.MySingleton3@8813f2:8918002
com.machome.singleton.MySingleton3@1d58aae:30771886
com.machome.singleton.MySingleton3@83cc67:8637543
com.machome.singleton.MySingleton3@e09713:14718739
com.machome.singleton.MySingleton3@de6f34:14577460
com.machome.singleton.MySingleton3@156ee8e:22474382
加入二次檢查
    public static MySingleton3 getInstance() throws InterruptedException {
        if(instance==null){
            synchronized(MySingleton3.class){
                if(instance==null){
                    Thread.sleep(10000);
                    instance = new MySingleton3();
                }
            }
        }
        return instance;
    }
執(zhí)行: 終于正確了
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051
com.machome.singleton.MySingleton3@1270b73:19336051 

  • 法2.采用"餓漢初始化"
 private static Singleton instance = new Singleton();
或者采用靜態(tài)塊
    private static final MySingleton1 instance;
    static {
        instance = new MySingleton1();
    }
   
 餓漢初始化根本不會(huì)存在線程安全問題,但開銷是個(gè)問題,因?yàn)閼袧h模式的使用理念是"用時(shí)才初始化",餓漢模式則是"不管用不用都初始化",這本身是和業(yè)界流行的資源使用習(xí)慣相違背的.
 不過因?yàn)樵硐鄬唵?而且初始化開銷畢竟總是一次性的,這個(gè)開銷也許值得犧牲.所以很多人還是選擇相對簡單的法2.
 
 
 
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
單例模式
5.3.8 在Java中一種更好的單例實(shí)現(xiàn)方式
Java多線程編程環(huán)境中單例模式的實(shí)現(xiàn)
單例模式 泛型
Java單例設(shè)計(jì)模式的實(shí)現(xiàn)
基于多線程任務(wù)隊(duì)列執(zhí)行時(shí)間測試——泛型單例模式落地
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服