<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          單例模式簡(jiǎn)單復(fù)雜,線程不安全到安全

          共 3315字,需瀏覽 7分鐘

           ·

          2020-11-19 21:26

          點(diǎn)擊上方「藍(lán)字」關(guān)注我們

          0x01 :簡(jiǎn)介

          說到單例模式,可以說單例模式是最常見,也是最常用的設(shè)計(jì)模式了。Spring的bean默認(rèn)就是單例的。雖然單例模式是最簡(jiǎn)單的設(shè)計(jì)模式,但是在實(shí)現(xiàn)上有多種方式,分別是餓漢式、懶漢式、雙重校驗(yàn)鎖;在線程安全方面有線程不安全的,也有線程相對(duì)安全的??偟膩碚f實(shí)現(xiàn)單例模式有以下一些特點(diǎn):

          1、私有的構(gòu)造方法

          2、內(nèi)部創(chuàng)建一個(gè)私有成員變量

          3、提供一個(gè)公開、靜態(tài)的獲取成員的方法

          類圖


          0x02:餓漢模式

          首先介紹一下最簡(jiǎn)單的單例模式(餓漢模式),這種方式在單例類被加載的時(shí)候?qū)嵗?/span>

          public?class?Singleton?{
          ??????//內(nèi)部創(chuàng)建一個(gè)私有成員變量
          ??????private?static?Singleton?instance?=?new?Singleton();;

          ??????private?Singleton()?{
          ???????????//私有的構(gòu)造方法
          ??????}

          ?????public?static?Singleton?getInstance()?{
          ?????????//提供一個(gè)公開、靜態(tài)的獲取成員的方法
          ?????????return?instance;
          ?????}
          ?}

          或者

          public?class?Singleton?{
          ??????
          //內(nèi)部創(chuàng)建一個(gè)私有成員變量
          ??????private?static?Singleton?instance;

          ??????static?{
          ??????????instance?=?new?Singleton();
          ??????}

          ??????private?Singleton()?{
          ???????????//私有的構(gòu)造方法
          ??????}

          ?????public?static?Singleton?getInstance()?{
          ?????????//提供一個(gè)公開、靜態(tài)的獲取成員的方法
          ?????????return?instance;
          ?????}
          ?}

          餓漢模式的缺點(diǎn)在于,如果單例對(duì)象的創(chuàng)建過程比較耗時(shí),那么將會(huì)導(dǎo)致應(yīng)用程序的啟動(dòng)比較慢。


          0x03:懶漢式

          為了克服餓漢模式的缺點(diǎn),將單例對(duì)象的創(chuàng)建過程延后到第一次使用單例對(duì)象時(shí),這種實(shí)現(xiàn)方式被稱為懶漢模式。

          public?class?Singleton?{

          ?????private?static?Singleton?instance;

          ??????private?Singleton()?{
          ??????}

          ??????public?static?Singleton?getInstance()?{
          ??????????if?(instance?==?null)?{
          ??????????????instance?=?new?Singleton();
          ?????????}
          ?????????return?instance;
          ?????}
          ?}

          需要注意的是懶漢式是線程不安全的。假設(shè)在單例類被實(shí)例化之前,有兩個(gè)線程同時(shí)在獲取單例對(duì)象,線程A在執(zhí)行完if (instance == null) 后,線程調(diào)度機(jī)制將 CPU 資源分配給線程B,此時(shí)線程B在執(zhí)行?if (instance == null)時(shí)也發(fā)現(xiàn)單例類還沒有被實(shí)例化,這樣就會(huì)導(dǎo)致單例類被實(shí)例化兩次。為了防止這種情況發(fā)生,需要對(duì) getInstance() 方法同步處理。改進(jìn)后的懶漢模式:

          public?class?Singleton?{
          ??????private?static?Singleton?instance;

          ??????private?Singleton()?{
          ??????}

          ??????//?線程安全的懶漢模式
          ??????public?synchronized?static?Singleton?getInstance()?{
          ??????????if?(instance?==?null)?{
          ?????????????instance?=?new?Singleton();
          ?????????}

          ?????????return?instance;
          ?????}
          ?}

          可以使用ReentrantLock對(duì)象進(jìn)行同步處理。改進(jìn)后的懶漢模式實(shí)現(xiàn)方式,每次獲取單例對(duì)象時(shí)都會(huì)加鎖,在多線程情況下會(huì)造成性能損耗。


          0x04:雙重校驗(yàn)鎖(double check)

          雙重校驗(yàn)鎖實(shí)現(xiàn)本質(zhì)也是一種懶漢式,相比懶漢式第2種實(shí)現(xiàn)方式將會(huì)有較大的性能提升。

          public?class?Singleton?{??
          ????
          private?static?Singleton?instance;??

          ????private?final?static?Object?lock?=?new?Object();??

          ????private?Singleton()?{??

          ????}??

          ????public?static?Singleton?getInstance(){??
          ????????if?(instance?==?null)?{??
          ????????????synchronized?(lock?)?{??
          ????????????????if?(instance?==?null)?{??
          ????????????????????instance?=?new?Singleton();??
          ????????????????}??
          ????????????}??
          ????????}??
          ????????return?instance;??
          ????}??
          }

          synchronized同步塊括號(hào)中的鎖定對(duì)象是采用的一個(gè)無關(guān)的Object類實(shí)例,而不是采用this,因?yàn)間etInstance是一個(gè)靜態(tài)方法,在它內(nèi)部不能使用未靜態(tài)的或者未實(shí)例的類對(duì)象,因此也可以這樣實(shí)現(xiàn)

          public?class?Singleton?{
          ??????private?volatile?static?Singleton?instance;

          ??????private?Singleton()?{
          ??????}

          ??????public?static?Singleton?getInstance()?{
          ??????????if?(instance?==?null)?{
          ??????????????synchronized?(Singleton.class)?{
          ?????????????????if?(instance?==?null)?{
          ?????????????????????instance?=?new?Singleton();
          ?????????????????}
          ?????????????}
          ?????????}
          ?????????return?instance;
          ?????}
          ?}

          就算在單例類被實(shí)例化時(shí)有多個(gè)線程,同時(shí)執(zhí)行了if (instance == null)的判斷,但同一時(shí)間點(diǎn)只有一個(gè)線程可以獲得鎖后進(jìn)入臨界區(qū)。通過if (instance == null)判斷的每個(gè)線程會(huì)依次獲得鎖進(jìn)入臨界區(qū),所以進(jìn)入臨界區(qū)后還要再判斷一次單例類是否已被其它線程實(shí)例化,以避免多次實(shí)例化。由于雙重加鎖實(shí)現(xiàn)僅在實(shí)例化單例類時(shí)需要加鎖,所以相較于懶漢式第2種實(shí)現(xiàn)方式會(huì)帶來性能上的提升。另外需要注意的是雙重加鎖要對(duì) instance 域加上 volatile關(guān)鍵字修飾符。由于 synchronized 并不是對(duì) instance 實(shí)例進(jìn)行加鎖(因?yàn)楝F(xiàn)在還并沒有實(shí)例),所以線程在執(zhí)行完?instance = new Singleton();修改 instance 的值后,應(yīng)該將修改后的 instance 立即寫入主存(main memory),而不是暫時(shí)存在寄存器或者高速緩沖區(qū)(caches)中,以保證新的值對(duì)其它線程可見。

          掃碼二維碼

          獲取更多精彩

          Java樂園

          有用!分享+在看?
          瀏覽 21
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91大神福利 | 五月天激情网站 | 秋霞欧美性爱 | 麻豆传剧原创在线观看 | 亚非日韩观看专区 |