1

マルチスレッド環境で共有変数にアクセスするコードがいくつかあります。明らかにlockこれらのアクセスのために必要ですが、私の質問は、値を取得するために短時間変数をロックし、ロックを解除し、取得したものでいくつかのことを行い、次に変更するために再度ロックすることで、追加のオーバーヘッドを節約または作成するかどうかです。ロックを解除したばかりのデータ構造。

ロックの外で実行できる非常にコストのかかる操作の場合は、明らかに、そのセグメントをロックしないことでメリットが得られます。たとえば、実行される操作が比較的安価な場合 (new objectとを作成if statement)は次のようになります。

ねじれが少ない:

Value v;
lock (values)
{
   v = values.FirstOrDefault(a => a.Thing == someValue);
   if (v == null)
   {
      v = new Value { Thing = someValue };
      values.Add(v);
   }
}

よりスレッド:

Value v;
lock (values)
{
   v = values.FirstOrDefault(a => a.Thing == someValue);
}


if (v == null)
{
   v = new Value { Thing = someValue };
   lock(values)
   {
      values.Add(v);
   }
}

どちらのソリューションもスレッドセーフであり、どちらも非常に読みやすい (IMHO) ですが、2 つにわずかな違いがある場合でも、より効率的な方を習慣に組み込むとよいでしょう。

4

2 に答える 2

2

2 つ目は、パフォーマンスを向上させる可能性がありますが、現実的には、Valueコンストラクターが比較的高価な場合にのみ問題になります。

2 番目のケースではlock、null チェック (非常に高速) を回避していますが、Valueインスタンスの構築中も回避しています。これにより、パフォーマンスが大幅に向上する可能性があります。

そうは言っても、これはスレッドセーフではありません。2 番目のスレッドは、2 つのロック ステートメントの間のコードに値を追加できます。そのため、最初のアプローチをお勧めします (valuesそのコレクションを使用する他の操作では常にロックする必要があることに注意してください)。

この検索が一般的なものである場合は、ConcurrentDictionary<T,U>代わりにThingas をキーとして使用することをお勧めします。次に、GetOrAddメソッドを使用して、値を安全に追加または取得できます。

于 2013-10-25T20:46:11.510 に答える