2012-05-07 4 views
11

早期のバインディングは、同期の問題を解決すると言います。私は "どのように"理解できませんでした。これはJavaにとって特別なものか、C++にも同じことが当てはまりますか?シングルトンパターン - 初期バインディング(静的変数を含む)は、ミューテックスロックの必要性を減らしますか?

この方法では、実際にはミューテックスロックは必要ありませんか?あなたはsingeltonメンバーは、あなたが作成のみを同期することができ 、最初の呼び出しまでヌル残ることをしたい場合には

enter image description here

+1

興味深いが、そのように使用するのではと思ったことはありません。私はいつも 'if(instance == null)インスタンス=新しいSingleton();'を使いました。しかし、専門家の言うことを見て待つつもり –

+0

上記のコメントは、この方法でメモリが保存することができます正しいです。なぜなら、最初のリクエストが来ると、オブジェクトが作成されるからです。 –

+0

これはいくつかの光を投げるかもしれないhttp://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-I/4/ – DumbCoder

答えて

3

私は、スレッドを開始/作成する前にSingletonインスタンスを作成することを指していると考えているため、作成時の同期の必要性が軽減されます。

EDIT:C++やC++で静的変数

をに関する情報を追加するデビッド・ハークネスのような実行は、Javaのために言及する前に、静的変数も初期化されます。 C++でのこの問題の1つは、システムが初期化されるまでmalloc/newへの呼び出しが実行されないような組み込み環境である可能性があります。この場合、シングルトン静的初期化子を使用すると問題が生じる可能性があります。

+0

@Anisha、上記の質問に答えた「David Harkness」、またはC++への参照を指していますか? – Brady

+0

いいえ、私はC++リファレンスについて話していました。しかし、その後、私は自分自身もいくつかの仕事をするべきだと思った。 :) –

+0

@アニシャ、あなたがstackoverflowで検索すると、関連する質問がたくさんあります。 – Brady

-2

。 例えば

+3

このコードは間違って危険です。 http://en.wikipedia.org/wiki/Double-checked_lockingを参照してください – interjay

+0

あなたのソリューションはスレッドセーフではありません。 '(singleton == null)'チェックの前に 'lock()'呼び出しを行い、 'if'ブロックの後に' unlock() '呼び出しを行いましたが、これはlock()/ unlock )オーバーヘッドを 'getInstance()'呼び出しごとに追加します。 –

+0

-1 Interjayが指摘しているように、このコードと関連するdouble-checked locking *はスレッドセーフではありません*。 –

11
getInstance() { 
    if (singleton == null) { 
     lock(); 
     if (singleton == null) { 
       singleton = new Singleton(); 
     } 
     unlock(); 
    } 
    return singleton; 
} 

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

+0

を確認してくれてありがとう。また、これはすべて「Java」に特有のものである。 –

+0

C#にも同様の保証があります。 –

+0

私は*完全にスレッドセーフであると思うと、あなたはフィールドfinalをマークする必要があります。 JVMは静的変数の初期化を強制しますが、JVMがメモリバリアを発行しない可能性があります。これは、別のスレッドが静的フィールドを初期化されていない状態で観察できることを意味します。 –

0

答えはYES!です。このメソッドを使用すると、 "get instance"のロックは必要ありません
--Edit--
オブジェクトの作成は、コードがロードされる前にロードされていることを保証するOSによって読み込みプロセスの一部ですランニング。
P.s.それはC++にも適用されます。
注:
1.「get instance」のロックは必要ありませんが、インスタンスの共有メンバーがある場合は必要になることがあります。
2.これは、インスタンスの初期化にパラメータを必要としない場合にのみ可能です。

+0

なぜ、どのように説明することができれば助けになります。シンプルなイエスとノーはあまり役に立ちません。 –

+0

質問は "そう、この方法では実際にはミューテックスロックは必要ありませんか?"答えは"はい "です(理由:オブジェクトの作成は、コードが実行される前にロードされていることを保証するOSによる読み込みプロセスの一部です) –

+0

質問には次の文も含まれます:*"あなたが正しい時には –

0

怠惰なインスタンス化が解決しようとしたことの1つ(C++関連だけでなく)はstatic initialization order fiascoでした。これは初期化の順序を(複数の翻訳単位で)ほとんど制御できないという問題ですが、依存関係ではオブジェクトがすでに存在してから別のオブジェクトを作成する必要があります。遅延インスタンス化では、オブジェクトは必要に応じて作成されるため、循環依存がない限り、大丈夫です。

getInstance()ごとにロックするコストを回避したい場合でも、Initialize()関数を追加してスレッドを開始する前に、すべてのシングルトンを初期化しても、あなたのクラス。こうすることで、シングルトンは一度しか初期化されず、初期化された後にのみアクセスされるというアサーションでチェックできます。それらがアクセスされたとき

  • 共有リソースがまだロックする必要があります。

    備考。

  • (他のコンパイラについてはわからないgccを使用している場合)、最も簡単な解決策は、getInstanceで静的関数変数を使用し、その変数への参照を返すことです。これはスレッドセーフです。

    class Example 
    { 
        ... 
        static Example& getInstance() 
        { 
        static Example instance; 
        return instance; 
        } 
    }; 
    
関連する問題