偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

雙重檢查鎖定失敗可能性

開(kāi)發(fā) 后端
雙重檢查鎖定在延遲初始化的單例模式中見(jiàn)得比較多(單例模式實(shí)現(xiàn)方式很多,這里為說(shuō)明雙重檢查鎖定問(wèn)題,只選取這一種方式).

雙重檢查鎖定在延遲初始化的單例模式中見(jiàn)得比較多(單例模式實(shí)現(xiàn)方式很多,這里為說(shuō)明雙重檢查鎖定問(wèn)題,只選取這一種方式),先來(lái)看一個(gè)版本:

 

  1. public class Singleton {  
  2.  
  3.     private static Singleton instance = null;  
  4.  
  5.     private Singleton(){}  
  6.  
  7.       
  8.  
  9.     public static Singleton  getInstance() {  
  10.  
  11.        if(instance == null) {  
  12.  
  13.            instance = new Singleton();  
  14.  
  15.        }  
  16.  
  17.        return instance;  
  18.  
  19.     }  
  20.  
  21. }  

 

上面是最原始的模式,一眼就可以看出,在多線(xiàn)程環(huán)境下,可能會(huì)產(chǎn)生多個(gè)Singleton實(shí)例,于是有了其同步的版本:

 

  1. public class Singleton {  
  2.  
  3.     private static Singleton instance = null;  
  4.  
  5.     private Singleton(){}  
  6.  
  7.       
  8.  
  9.     public synchronized static Singleton getInstance() {  
  10.  
  11.        if(instance == null) {  
  12.  
  13.            instance = new Singleton();  
  14.  
  15.        }  
  16.  
  17.        return instance;  
  18.  
  19.     }  
  20.  
  21. }  

 

在這個(gè)版本中,每次調(diào)用getInstance都需要取得Singleton.class上的鎖,然而該鎖只是在開(kāi)始構(gòu)建Singleton 對(duì)象的時(shí)候才是必要的,后續(xù)的多線(xiàn)程訪(fǎng)問(wèn),效率會(huì)降低,于是有了接下來(lái)的版本:

 

  1. public class Singleton {  
  2.  
  3.     private static Singleton instance = null;  
  4.  
  5.     private Singleton(){}  
  6.  
  7.       
  8.  
  9.     public static Singleton getInstance() {  
  10.  
  11.        if(instance == null) {  
  12.  
  13.            synchronized(Singleton.class) {  
  14.  
  15.               if(instance == null) {  
  16.  
  17.                   instance = new Singleton();  
  18.  
  19.               }  
  20.  
  21.            }  
  22.  
  23.        }  
  24.  
  25.        return instance;  
  26.  
  27.     }  
  28.  
  29. }  

 

很好的想法!不幸的是,該方案也未能解決問(wèn)題之根本:

原因在于:初始化Singleton 和 將對(duì)象地址寫(xiě)到instance字段 的順序是不確定的。在某個(gè)線(xiàn)程new Singleton()時(shí),在構(gòu)造方法被調(diào)用之前,就為該對(duì)象分配了內(nèi)存空間并將對(duì)象的字段設(shè)置為默認(rèn)值。此時(shí)就可以將分配的內(nèi)存地址賦值給instance字段了,然而該對(duì)象可能還沒(méi)有初始化;此時(shí)若另外一個(gè)線(xiàn)程來(lái)調(diào)用getInstance,取到的就是狀態(tài)不正確的對(duì)象。

鑒于以上原因,有人可能提出下列解決方案:

 

  1. public class Singleton {  
  2.  
  3.     private static Singleton instance = null;  
  4.  
  5.     private Singleton(){}  
  6.  
  7.       
  8.  
  9.     public static Singleton getInstance() {  
  10.  
  11.        if(instance == null) {  
  12.  
  13.            Singleton temp;  
  14.  
  15.            synchronized(Singleton.class) {  
  16.  
  17.               temp = instance;  
  18.  
  19.               if(temp == null) {  
  20.  
  21.                   synchronized(Singleton.class) {  
  22.  
  23.                      temp = new Singleton();  
  24.  
  25.                   }  
  26.  
  27.                   instance = temp;  
  28.  
  29.               }  
  30.  
  31.            }  
  32.  
  33.        }  
  34.  
  35.        return instance;  
  36.  
  37.     }  
  38.  
  39. }  

 

該方案將Singleton對(duì)象的構(gòu)造置于最里面的同步塊,這種思想是在退出該同步塊時(shí)設(shè)置一個(gè)內(nèi)存屏障,以阻止初始化Singleton 和 將對(duì)象地址寫(xiě)到instance字段 的重新排序。

不幸的是,這種想法也是錯(cuò)誤的,同步的規(guī)則不是這樣的。退出監(jiān)視器(退出同步)的規(guī)則是:所以在退出監(jiān)視器前面的動(dòng)作都必須在釋放監(jiān)視器之前完成。然而,并沒(méi)有規(guī)定說(shuō)退出監(jiān)視器之后的動(dòng)作不能放到退出監(jiān)視器之前完成。也就是說(shuō)同步塊里的代碼必須在退出同步時(shí)完成,而同步塊后面的代碼則可以被編譯器或運(yùn)行時(shí)環(huán)境移到同步塊中執(zhí)行。

編譯器可以合法的,也是合理的,將instance = temp移動(dòng)到最里層的同步塊內(nèi),這樣就出現(xiàn)了上個(gè)版本同樣的問(wèn)題。

在JDK1.5及其后續(xù)版本中,擴(kuò)充了volatile語(yǔ)義,系統(tǒng)將不允許對(duì) 寫(xiě)入一個(gè)volatile變量的操作與其之前的任何讀寫(xiě)操作 重新排序,也不允許將 讀取一個(gè)volatile變量的操作與其之后的任何讀寫(xiě)操作 重新排序。

在jdk1.5及其后的版本中,可以將instance 設(shè)置成volatile以讓雙重檢查鎖定生效,如下:

 

  1. public class Singleton {  
  2.  
  3.     private static volatile Singleton instance = null;  
  4.  
  5.     private Singleton(){}  
  6.  
  7.       
  8.  
  9.     public static Singleton getInstance() {  
  10.  
  11.        if(instance == null) {  
  12.  
  13.            synchronized(Singleton.class) {  
  14.  
  15.               if(instance == null) {  
  16.  
  17.                   instance = new Singleton();  
  18.  
  19.               }  
  20.  
  21.            }  
  22.  
  23.        }  
  24.  
  25.        return instance;  
  26.  
  27.     }  
  28.  
  29. }  

 

需要注意的是:在JDK1.4以及之前的版本中,該方式仍然有問(wèn)題。

【編輯推薦】

  1. 有趣的Java對(duì)象序列化緩存問(wèn)題
  2. 關(guān)于Java對(duì)象序列化您不知道的5件事
  3. Java 7 I/O新功能探秘:同步操作,多播與隨機(jī)存取
  4. Java實(shí)用技巧:當(dāng)不能拋出checked異常時(shí)
  5. 多線(xiàn)程開(kāi)發(fā)的捷徑:構(gòu)建Java并發(fā)模型框架
責(zé)任編輯:金賀 來(lái)源: ITEYE博客
相關(guān)推薦

2016-11-11 00:33:25

雙重檢查鎖定延遲初始化線(xiàn)程

2022-12-30 07:40:12

DeepKitTypeScript靜態(tài)類(lèi)型

2013-12-23 09:48:43

C++鎖定模式

2013-11-29 09:51:26

C++雙重檢查鎖定

2018-03-02 11:38:11

2011-04-18 13:43:42

2017-07-21 16:40:29

網(wǎng)易云場(chǎng)景專(zhuān)屬云

2016-09-21 09:16:55

Qlik

2023-10-27 14:25:26

組件庫(kù)無(wú)限可能性

2012-06-04 13:28:51

AndroidChrome OS

2021-02-20 12:04:51

比特幣區(qū)塊鏈美元

2018-11-26 09:48:57

服務(wù)器異常宕機(jī)

2019-04-15 10:30:38

程序員技能開(kāi)發(fā)者

2009-03-11 18:27:04

Windows 7商業(yè)版

2020-08-11 09:38:40

微信蘋(píng)果美國(guó)

2011-04-18 13:47:59

ECC私鑰

2019-04-22 08:57:46

硅谷996ICU

2020-05-15 13:42:03

物聯(lián)網(wǎng)人工智能軍事物聯(lián)網(wǎng)

2013-03-19 11:13:14

Google廣告SXSW

2020-07-24 10:14:17

網(wǎng)絡(luò)安全黑客技術(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)