阿布的天空,只做收集...                                                                                                    Manage    NewBlog    Exit


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

Welcome to iPUD's Sky!


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:阿布的天空
日志总数:29
评论数量:39
留言数量:-32
访问次数:165210
建立时间:2006年3月21日




[JAVA学习]Singleton pattern, Double-checked Locking pattern
文章收藏,  网上资源,  软件技术

阿布 发表于 2006/4/2 14:42:09

koji http://www.jsptw.com/jute/post/view?bid=25&id=3939&sty=1&tpg=2&age=0 double-checked locking範例n 1234567891011 public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 if (instance == null) //2 instance = new Singleton(); //3 } } return instance; } 表面上看來不會有問題 但是在實際上java環境下跑起來可能會如下的問題發生 這是因為現在的java環境下memory model的關係,允許out of order寫入(這邊中文不知這樣可不可以) 1.thread1 進入getInstance() 2.instance是null,所以thread1進入synchronized block 3.thread1執行到//3讓instance變成非null,但是此時並無執行constructor 4.thread1切換到thread2 5.thread2檢查instance是否是null,但是因為instance並非null,所以thread2只把雖已建構,但並無完全出始化的Singleton物件,參考到instance並取得. 6.thread2切換到thread1 7.thread1執行constructor並取得其參考,完成Singleton物件的初期化 另外一種,試圖解決out of order的做法 1234567891011121314151617 public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 Singleton inst = instance; //2 if (inst == null) { synchronized(Singleton.class) { //3 inst = new Singleton(); //4 } instance = inst; //5 } } } return instance; } 主要為了避免之前的問題,導入了synchronized和使用inst變數的做法 理由如下 1.thread1 進入getInstance() 2.instance是null,所以thread1進入synchronized block 3.變數inst取得instance的值,//2但是為null 4.因為inst為NULL,所以thread1會在//3進入第二個synchronized block 5.接下來thread1於//4執行code,將inst改成非null,但是此時並無執行Singleton的constructor(也就是上面範例的缺陷發生原因) 6.thread1切換到thread2 7.thread2進入getInstance() 8.因為instance為null,因此thread2於//1會想進入synchronized block,但是現在被thread1所鎖住. 9.切換到thread1//4的部分被執行完畢 10.thread1將完整建構好的 Singleton 物件傳回給變數instance//5,結束兩個synchronized block 11.thread1回傳instance 12.接下來回到thread2,//2將instance代入到inst 13.thread2知道instance並非null,因此回傳instance 關鍵在於//5的部分,在寫上述範例中必須假設成,instance必須將會變成null或者是完全建構好的 Singleton 物件.當這個假設和事實衝突時,就是問題發生的原因了. 依照現行的memory model的定義,上面這個code將不會得到如我們預想的結果 ,JLS定義中無法將synchronized block內的code搬到外面,但是並沒有說明能將synchronized block外的搬到內部. jit compiler應該會抓住這部分,當作是最佳化的好機會,他會將//4和//5除去並結合,因此最佳化以後會變如下,同樣會造成out of order的問題. 123456789101112131415161718 public static Singleton getInstance() { if (instance == null) { synchronized(Singleton.class) { //1 Singleton inst = instance; //2 if (inst == null) { synchronized(Singleton.class) { //3 //inst = new Singleton(); //4 instance = new Singleton(); } //instance = inst; //5 } } } return instance; } 解決方式就像之前板上大家討論的 要碼就是 123456 public static synchronized Singleton getInstance() { if (instance == null) //1 instance = new Singleton(); //2 return instance; //3 } 不然就是 123456789101112131415161718 class Singleton { private Vector v; private boolean inUse; private static Singleton instance = new Singleton();   private Singleton() { v = new Vector(); inUse = true; //... }   public static Singleton getInstance() { return instance; } } 底下那個String的測試code 在IBM 1.3 JVM和Sun 1.3 JVM沒有問題 但是在譬如舊的版本如1.2下 會產生問題 且會執行 System.out.println("String is not immutable!");


阅读全文(2303) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.268 second(s), page refreshed 144765087 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号