日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

单例双重加锁

發(fā)布時(shí)間:2024/4/15 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单例双重加锁 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  相信面向?qū)ο蟪绦騿T都對(duì)單例模式比較熟悉,而對(duì)于單例模式卻有著各種各樣的寫法,今天我專門針對(duì)一種稱為雙重加鎖的寫法進(jìn)行分析。我們先來(lái)看下這種寫法。

/*** 單例雙重加鎖Demo**/ public class DoubleCheckLock {private static DoubleCheckLock instance ;private DoubleCheckLock(){}public static DoubleCheckLock getInstance(){if(instance == null){synchronized (DoubleCheckLock.class) {if(instance == null)instance = new DoubleCheckLock() ;}}return instance;} }

  這種寫法相信很多人都見(jiàn)過(guò),但是你認(rèn)為這種寫法是正確的嗎?或者更準(zhǔn)確的來(lái)說(shuō),這種寫法在并發(fā)的環(huán)境下是否還能表現(xiàn)出正確的行為呢。

  之所以有這種所謂的雙重加鎖,一方面是因?yàn)檠舆t初始化可以提高性能,另一方面通過(guò)使用內(nèi)置鎖sychronized來(lái)防止并發(fā),其原理是首先檢查是否在沒(méi)有同步的情況下進(jìn)行了初始化,如果沒(méi)有的話,在進(jìn)行同步,然后再次檢查是否對(duì)其(instance)進(jìn)行了初始化,如果沒(méi)有那么則初始化DoubleCheckLock。

  這種寫法表面看起來(lái)既提高了性能,又保證了線程安全。但實(shí)際上卻并不是如此,我只從線程安全上來(lái)分析這種寫法的對(duì)錯(cuò)。

  在這,首先應(yīng)該注意的是使用內(nèi)置鎖加鎖的是DoubleCheckLock.class,并不是instance,也就是說(shuō)沒(méi)有在instance實(shí)現(xiàn)同步,那么在這種情況下,當(dāng)有兩個(gè)線程同時(shí)進(jìn)行到synchronized代碼塊時(shí),只有一個(gè)線程可以進(jìn)入,然后初始化了instance,但是這僅僅只能保證的是兩個(gè)線程在訪問(wèn)上的獨(dú)占性,也就是說(shuō)兩個(gè)線程在此一定是一先一后進(jìn)行訪問(wèn),但是不能保證的是instance的內(nèi)存可見(jiàn)性,原因很簡(jiǎn)單,因?yàn)橥降膶?duì)象并不是instance,而是DoubleCheckLock.class(可以保證內(nèi)存可見(jiàn)性)。不能保證內(nèi)存可見(jiàn)性的后果就是當(dāng)?shù)谝粋€(gè)線程初始化instance之后,第二個(gè)線程并不能馬上看見(jiàn)instance被初始化,或者更準(zhǔn)確的來(lái)說(shuō),第二個(gè)線程看到的可能只是被部分構(gòu)造的instance。因此,這種造成的后果是第二個(gè)線程讀取到了錯(cuò)誤的instance的狀態(tài),有可能instance會(huì)被再次實(shí)例化。

  那么如何解決這個(gè)問(wèn)題呢,最簡(jiǎn)單的方式是對(duì)instance加上關(guān)鍵詞volatile,volatile可以保證變量的內(nèi)存可見(jiàn)性,同時(shí)volatile同步的消耗也非常小,這么做到話,可以保證線程安全。

  上述解決問(wèn)題的方式固然是可以,但是實(shí)質(zhì)上我感覺(jué)很繁瑣其代碼閱讀效果也不好,就單例而言,我推薦一下的寫法。

public class Single {private Single(){}private static class SingleHolder{public static Single instance = new Single();}public static Single getInstance(){return SingleHolder.instance;} }

  這種寫法相對(duì)而言比較簡(jiǎn)單,而且處理了兩個(gè)問(wèn)題:1.線程安全問(wèn)題。2.延遲初始化(初始化在調(diào)用getInstance的時(shí)候才會(huì)去靜態(tài)內(nèi)部類中初始化instance)。而且相對(duì)而言,有著更加良好的代碼可讀性。

  對(duì)于雙重加鎖的這種寫法就先分析到這,等后面說(shuō)到Happens-Before之后我會(huì)再來(lái)分下下雙重加鎖。

?

轉(zhuǎn)載于:https://www.cnblogs.com/yanfengfree/p/6271359.html

總結(jié)

以上是生活随笔為你收集整理的单例双重加锁的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。