6

シングルトンパターンに二重チェックロックイディオムを使用する方が良いですか? それとも同期方式?

すなわち:

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
 }
4

5 に答える 5

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();
    }
}
于 2013-03-20T14:54:27.177 に答える
0

最初のオプションは正しいダブルチェックロックの実装ですが、ProcessManagerクラスにgetInstance以外のパブリックメソッドがない場合、必要なのは

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

  private ProcessManager() {
  }

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

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

于 2013-03-20T15:10:26.207 に答える
0

最初のオプション。

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

getInstance()呼び出しでは、インスタンスのがチェックされ、nullnullの場合はすぐに構築されてから、instanceが返されます。

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

これも参照してください。

于 2013-03-20T15:00:32.580 に答える
0

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

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

于 2013-03-20T14:53:16.667 に答える
0

遅延読み込みが必要な場合は、同期された方法ではなく、ダブルチェックに従います。最後に、問題はvolatile と synchronizedの問題です:

Volatile は、volatile 変数へのすべてのアクセス (読み取りまたは書き込み) をメイン メモリに強制的に発生させ、CPU キャッシュから volatile 変数を効果的に排除します。これは、変数の可視性が正しく、アクセスの順序が重要ではないことが単に必要な一部のアクションにとって重要な場合があります。

インスタンスが初期化されると、同期ブロックは実行されません (ただし、競合状態のため)。支払われる唯一の同時実行コストは、volatile 変数への 1 回の読み取りのコストです。

有効な Java Bloch では、ローカル変数に volatile フィールドをロードするとパフォーマンスが向上すると述べていることに注意してください(揮発性の読み取りが少ないためだと理解しています)。

 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;
}
于 2013-03-20T15:17:06.310 に答える