4

それについて読んだLazyInitializer 、それは次のとおりです。

複数のスレッドが競合して初期化する別の初期化モードを提供します。

ここにサンプルがあります:

Expensive _expensive;
public Expensive Expensive
     {
       get // Implement double-checked locking
         {
           LazyInitializer.EnsureInitialized (ref _expensive,() => new Expensive());
           return _expensive;
         }
     }

質問1

見つめている : ここに画像の説明を入力

#A がダブルチェック ロックを実装していると言うのはなぜですか? それは単なるgetプロパティですか?

質問2

#B (ラムダ式) はスレッドセーフですか?

質問#3

そこで、サンプルを見て、この「初期化の競合」について検索しました。

volatile Expensive _expensive;
public Expensive Expensive
{
  get
  {
    if (_expensive == null)
    {
      var instance = new Expensive();
      Interlocked.CompareExchange (ref _expensive, instance, null);
    }
    return _expensive;
  }
}

それから私は考えました:初期化するレースはスレッドセーフですか?

e/g/ 2 つのスレッドが入った場合:

ここに画像の説明を入力

高価なオブジェクトが 2 回作成されます。

もう一度、3つの質問

1) なぜ #A は、ダブルチェック ロックを実装していると言うのですか? それは単なるgetプロパティですか?

2) #B (ラムダ式) はスレッドセーフですか?

3)初期化するレースはスレッドセーフではありません

4

1 に答える 1

5

にはさまざまなオーバーロードがありEnsureInitializedます。synclockオブジェクトを受け入れるものもあります(メソッドnullによって作成される可能性があり、作成される予定ですEnsureInitialized)。synclock他のものはパラメーターとしてを持っていません。EnsureInitializedオブジェクトが初期化されていないときに 2 つ (またはそれ以上) の異なるスレッドによって同時に呼び出された場合、2 つのスレッドが同じオブジェクトへの参照を受け取ることがすべて保証されます。そう:

Expensive _expensive;

// On thread 1
LazyInitializer.EnsureInitialized (ref _expensive,() => new Expensive());

// On thread 2
LazyInitializer.EnsureInitialized (ref _expensive,() => new Expensive());

2 つの_expensiveスレッドから見えるオブジェクトは同じになります。

唯一の問題は、new Expensive()2 回呼び出される可能性があることです (スレッドごとに 1 回なので、マルチスレッド レースではさらに複数回呼び出される可能性があります)。

必要ない場合は、synclockオーバーロードを使用してください。

Expensive _expensive;
object _sync = null;
bool _useless;

// On thread 1
LazyInitializer.EnsureInitialized (ref _expensive, ref useless, ref _sync, () => new Expensive());

// On thread 2
LazyInitializer.EnsureInitialized (ref _expensive, ref useless, ref _sync, () => new Expensive());

これで、new Expensive()実行中の 2 つ (またはそれ以上) のスレッドの可能な組み合わせごとに、 が 1 回だけ呼び出されます。

于 2012-07-19T07:59:26.457 に答える