11

彼らは、早期バインディングが同期の問題を解決すると言います。「どうやって」理解できませんでした。これはJavaにとって特別なことですか、それとも同じことがC ++にも当てはまりますか?

したがって、この方法では、実際にはミューテックスロックは必要ありませんか?

ここに画像の説明を入力してください

4

5 に答える 5

11

JVMは、他のスレッドを介したクラスへのアクセスを許可する前に、各クラスが完全にロードされていることを確認します。これは、uniqueInstance上記を含むすべての静的変数が、アクセスされる前に完全にインスタンス化されることを意味します。これはJavaに固有であり、インスタンスの公開を保護するために同期を行う必要がないことを意味します。

于 2012-05-07T08:40:14.303 に答える
3

スレッドを開始/作成する前にシングルトンインスタンスを作成することを指していると思います。これにより、作成時の同期の必要性が軽減されます。

編集:C++と静的変数に関する情報を追加する

C ++では、David HarknessがJavaについて述べているように、静的変数も実行前に初期化されます。C ++でのこれに関する1つの問題は、システムが初期化されるまでmalloc / newの呼び出しを実行できない組み込み環境で発生する可能性があります。この場合、シングルトン静的初期化子の使用が問題になる可能性があります。

于 2012-05-07T08:40:59.393 に答える
0

答えはYES!です。
このメソッドでは、「getinstance」 --Edit--のロックは必要ありません。
その理由は、オブジェクトの作成がOSによるロードプロセスの一部であり、コードが実行される前にオブジェクトがロードされることを保証するためです。
PSそれはC++にも適用されます。
注:
1。「インスタンスの取得」のロックは必要ありませんが、インスタンスの共有メンバーがある場合は必要になる場合があります。
2.これは、インスタンスの初期化にパラメーターが必要ない場合にのみ可能です。

于 2012-05-07T08:43:34.680 に答える
0

レイジーインスタンス化が解決しようとしたことの1つ(C ++関連だけでなく)は、静的初期化順序の大失敗でした。これは、初期化の順序(複数の変換ユニットを使用)をほとんど制御できないという問題ですが、依存関係では、オブジェクトを作成する前に、オブジェクトがすでに存在している必要がある場合があります。遅延インスタンス化では、オブジェクトは必要に応じて作成されるため、循環依存関係がない限り、問題はありません。

依存関係が問題であり、各getInstance()のロックのコストを回避したい場合でも、クラスにInitialize()関数を追加して、スレッドを開始する前にすべてのシングルトンを初期化することで、熱心なインスタンス化を行うことができます。このようにして、シングルトンが一度だけ初期化され、初期化された後にのみアクセスされることをアサートで確認できます。

次のことに注意してください。

  • 共有リソースにアクセスするときは、引き続きロックする必要があります。
  • C ++ 11以降(および他のコンパイラについてはよくわからないためgccを使用する場合)、最も簡単な解決策は、getInstanceで静的関数変数を使用し、その変数への参照を返すことです。これはスレッドセーフです。

    class Example
    {
      ...
      static Example& getInstance()
      {
        static Example instance;
        return instance;
      }
    };
    
于 2012-05-07T11:28:06.200 に答える
-2

単一のメンバーを最初の呼び出しまでnullのままにしておきたい場合は、作成物のみを同期できます。例えば

getInstance() {
     if (singleton == null) {
         lock();
         if (singleton == null) {
               singleton = new Singleton();
         }
         unlock();
     }
     return singleton;
}
于 2012-05-07T08:38:33.187 に答える