JWorld@TW the best professional Java site in Taiwan
      註冊 | 登入 | 全文檢索 | 排行榜  

» JWorld@TW » Software Design » GoF  

按列印兼容模式列印這個話題 列印話題    把這個話題寄給朋友 寄給朋友    訂閱主題
reply to topicthreaded modego to previous topicgo to next topic
本主題所含的標籤
無標籤
作者 Re:[DP]Singleton pattern, Double-checked Locking pattern (by Biologic) [Re:popcorny]
plutotw

井底蛙



發文: 624
積分: 3
於 2004-09-02 09:47 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
這是我看了討論串後,整理出的模式,這樣在多 thread 下還可能會引發什麼問題嗎 ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Test {
private static  Object resource = null;
private static  boolean standby = false ;
 public Object getObject() {
  if ( standby )
    return resource ;
   synchronized ( Test.class ) {
      if ( ! standby ) { // 避免 synchronized  前一個 thread 已完成配置
       resource = new Object();
      standby = true ;
     }
   }
   return resource;
 }
} 


plutotw edited on 2004-09-02 09:59
reply to postreply to post
作者 Re:[DP]Singleton pattern, Double-checked Locking pattern (by Biologic) [Re:plutotw]
alien

小弟劣作一幅



發文: 772
積分: 6
於 2004-09-03 09:01 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
plutotw wrote:
這是我看了討論串後,整理出的模式,這樣在多 thread 下還可能會引發什麼問題嗎 ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Test {
private static  Object resource = null;
private static  boolean standby = false ;
 public Object getObject() {
  if ( standby )
    return resource ;
   synchronized ( Test.class ) {
      if ( ! standby ) { // 避免 synchronized  前一個 thread 已完成配置
       resource = new Object();
      standby = true ;
     }
   }
   return resource;
 }
} 



問得好.

我之前也有問過一模一樣的問題.

(我是寄去問 http://www-106.ibm.com/developerworks/java/library/j-dcl.html#author1 此文的作者的), 這是他的回答.

Your code is not guaranteed to work.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MySingleton {
 private static MySingleton instance = null;
 private staitc bool singletonInitialized = false;
 
 MySingleton getInstance() {
   if (!singletonInitailized) {
     synchronized (MySingleton.class) {
       if (!singletonInitialized) {
         instance = new MySingleton();
         signletonInitialized = true;  //1
       }
     }
   } 
        return instance; //you forgot this
 } 


One problem is that if T1 blocks after executing //1 but before exiting the synchronized block, Thread 2 can call getIntance and see the boolean as true, but return a Singleton object whose ctor has not run yet. This can happen because the sync block from T1 has not exited yet and therefore, instance has not been flushed to main memory. Therefore, there are no guarantees to what T1 will see when it returns instance.

The bottom line problem is that you are setting the singletonInitialized variable inside a synchronized block, but reading it outside of any synchronized block. Any variable that can is read or written by multiple threads must be accessed with proper synchronization techniques to guarantee valid values and behavior.

Peter

-----------------
個人覺得他的答案好像有點怪怪的. 因為時間問題沒有再去追問了.

記得是有找到過一些 info, 有關 sync block 裡的 data assignment 是不會在立刻生效, 還得 flush 到 main memory之類的, 但詳細說的是不是這種情況, 我還沒去看清楚.


alien edited on 2004-09-03 15:38
reply to postreply to post

public class Alien {
public boolean isNewbie() {
return true;
}
public String toString() {
return "請大家多多指教";
}
}
作者 Re:[DP]Singleton pattern, Double-checked Locking pattern (by Biologic) [Re:alien]
plutotw

井底蛙



發文: 624
積分: 3
於 2004-09-03 21:03 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
alien wrote:

以下這樣不知是否能解決問題
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MySingleton {
 private static MySingleton instance = null;
 private staitc boolean singletonInitialized = false;
 
public static  MySingleton getInstance() {
   if (!singletonInitailized) {
     synchronized (MySingleton.class) {
       if (!singletonInitialized) {
         instance = new MySingleton();
         signletonInitialized = true;  //1
       }
     }
   } 
   while ( instance == null ) { // 等待至正常
    try { 
    Thread.sleep(100) ;
    } catch (Exception e ) {
    }
  } 
 
         return instance; //you forgot this
 } 

如果 synchronized 機制會造成問題的話 , 那是否
synchronized 此 method 的方式也會引發相同的問題 ?


plutotw edited on 2004-09-03 21:06
reply to postreply to post
作者 Re:[DP]Singleton pattern, Double-checked Locking pattern (by Biologic) [Re:popcorny]
zanyking





發文: 406
積分: 4
於 2005-08-24 13:43 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
回上一篇。

應該不會吧,因為今天擔心的就是複數的外部程式同時呼叫getInstance,而不小心重建這個Singleton物件兩次。在getInstance的飾詞為Static synchronized 的情況下JVM應該必須確保絕對只有一個外部程序能進來。

private staitc boolean singletonInitialized = false;可能要volatile,不然多處理器系統可能會有問題。

說一下對這個討論串的感想好了。

很久以前剛剛學JAVA,根本不知道在講什麼。
剛剛考完SCJP,好像知道有什麼。
現在程式寫了幾支,終於知道大概在說什麼。

我自己個人覺得,會去考慮Singleton的DCL,應該只在幾個條件同時成立下,才會想要用:

1.這個Singleton同時被很多thread叫用。
2.這個Singleton中有某些成員的產生極度消耗系統資源。
3.如上,這些成員不能由外部的程式產生後提供。(例如對硬體的操作)
4.除了初始化這些成員外,外部程式因為某些原因,只能夠透過getInstance傳入某些參數對singleton作很Heavy Loading 的Config。
(也就是synchronized 區塊內,還有很多雜七雜八的作業與外部程式有關,不然就直接宣告整個methode synchronized不就好了?反正初始化就只能作一次,一支thread搶去作,其他thread等不就得了?)

想到的大概有這些,不曉得大家覺得如何?


reply to postreply to post
作者 Re:[DP]Singleton pattern, Double-checked Locking pattern (by Biologic) [Re:popcorny]
shukae





發文: 70
積分: 0
於 2010-12-17 14:42 user profilesend a private message to userreply to postreply to postsearch all posts byselect and copy to clipboard. 
ie only, sorry for netscape users:-)add this post to my favorite list
搜尋到這篇...
回應一下我的看法(這玩法我也常用, 而且更複雜)
用DCL的作法必然是不想要馬上建立該instance
又必須兼顧到效能與多執行緒問題
所以用兩個if一個sync來控制
但是當多CPU環境可能就會遇到先assignment後constructor的問題
還有JIT也會自己把程式碼最佳化.......
這問題我認為要解決也不是那麼難
我的構想是『呼叫method』,原因基於下列兩項假設
1. JIT compiler 不會把method合併
2. JIT compiler不會把看似沒用method呼叫刪除掉
所以
instance 建立的過程,呼叫一個method
在method 中將物件建立之後呼叫一個該物件的method
例如呼叫hashCode(), 能被呼叫必然已經完成物件的建立
之後才return並且assignment
這樣就可以解決這些問題

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TTT {
 
  private static TTT my;
 
  public static TTT getInstance(){
    if(my==null){
      synchronized (TTT.class) {
        if(my==null){
          my = create(); // 以呼叫method方式指派, 避免被最佳化時程式碼被合併
        }
      }
    }
    return my;
  }
 
  protected static TTT create(){
    TTT tmp = new TTT(); // 建立物件與下面的hashCode()/return有相依性, 不可能被CPU同時執行
    tmp.hashCode();  // 呼叫某個 Method, 以確保物件建構完成
    return tmp;
  }
 
}


shukae edited on 2011-01-24 12:58
reply to postreply to post
go to first page go to previous page  1   2  go to next page go to last page
» JWorld@TW »  Software Design » GoF

reply to topicthreaded modego to previous topicgo to next topic
  已讀文章
  新的文章
  被刪除的文章
Jump to the top of page

JWorld@TW 本站商標資訊

Powered by Powerful JuteForum® Version Jute 1.5.8