2013-03-20 5 views
5

シングルトンパターンにダブルチェックロックイディオムを使用する方が良いですか?または、同期メソッド?シングルトンパターンにダブルチェックロックイディオムを使用するのが最適ですか?

すなわち:

private static volatile ProcessManager singleton = null; 

public static ProcessManager getInstance() throws Exception { 

    if (singleton == null) { 
     synchronized (MyClass.class) { 
      if (singleton == null) { 
       singleton = new ProcessManager(); 
     } 
     } 
    } 
    return singleton; 

}

または

private static processManager singleton = null; 

public synchronized static processManager getInsatnce() throws Exception { 

    if(singleton == null) { 
      singleton = new processManager(); 
    } 

    return singleton 
} 
+0

を高めることを言うこと

注意あなたの2番目のコードのように、意味をなさない。 – Jesper

+4

あなた自身の前の質問に[この回答](http://stackoverflow.com/a/15498689/1103872)で説明されているように、上記のどれもありません。 –

+0

2番目の例では、すでに重大なセクションに入っているので、ダブルチェックは必要ありません(あなたのクラスのどこかでシングルトンメンバーに触れていないと仮定して) – Grimmy

答えて

0

基本的には、2つ目のオプションは、追加の保証を追加しません。

より頻繁にチェックしますが、同時アクセスは引き続き発生する可能性があります。そのため、2つのインスタンスが発生する可能性は低くなりますが、それを排除することはできません。

6

は、ClassLoaderを持っているあなたのための仕事をする:

/* 
    * This solution takes advantage of the Java memory model's guarantees about class initialization 
    * to ensure thread safety. Each class can only be loaded once, and it will only be loaded when it 
    * is needed. That means that the first time getInstance is called, mySingletonServiceLoader 
    * will be loaded and instance will be created, and since this is controlled by ClassLoaders, 
    * no additional synchronization is necessary. 
    */ 
    public static DocumentService getInstance() { 
     return mySingletonServiceLoader.INSTANCE; 
    } 

    private static class mySingletonServiceLoader { 
     static DocumentService INSTANCE = new DocumentService(); 
    } 
} 
0

最初のオプション。

単一インスタンスの複数のバージョンを作成する機能があります... getInstance

は()インスタンスを呼び出すnullをチェックし、それがnullの場合、すぐに構築され、その後、instanceされます返されます。

スレッドセーフである必要があります。

thisも参照してください。

0

最初のオプションが正しいダブルチェックロックの実装ですが、ProcessManagerクラスにはより多くのパブリックメソッドが存在しない場合はのgetInstanceは、あなたが必要とするすべては

public class ProcessManager { 
    private static ProcessManager instance; 
    static { 
     instance = new ProcessManager(); 
    } 

    private ProcessManager() { 
    } 

    public static ProcessManager getInstance() { 
     return instance; 
    } 
} 

クラスが最初ProcessManagerにロードされ、初期化されますです.getInstance()の呼び出し

0

遅延ロードが必要な場合は、を使用すると、同期メソッドの代わりにダブルチェックを使用します。

揮発性、単純に効果的にCPUのキャッシュのうち、揮発性変数を保ち、メインメモリに発生する揮発性変数へのすべてのアクセス(読み取りまたは書き込み)強制:最後に、問題がvolatile vs. synchronizedのことです。これは、変数の可視性が正しいこととアクセスの順序が重要ではないことが単純に要求されるいくつかのアクションにとって重要になります。

インスタンスが初期化されると、同期ブロックは実行されません(競合条件の場合)。支払われる唯一の並行処理コストは、揮発性変数への1回の読み込みです。に効果的なJavaのブロッホは、ローカル変数にvolatileフィールドをロードすると、パフォーマンス(私は少数の揮発性があるので、それが読み取りであることを理解)

の間には何もない2つのネストされたIFSを持つ
public static ProcessManager getInstance() throws Exception { 
    ProcessManager result = singleton; 
    if (result == null) { 
    synchronized (MyClass.class) { 
     result = singleton; 
     if (result == null) { 
      singleton = result = new ProcessManager();    
     } 
    } 
    return result; 
} 
関連する問題