5

C# でスレッド同期を行う場合、値を読み取ったり変更したりするときにオブジェクトをロックする必要がありますか?

たとえば、Queue<T> オブジェクトがあります。Enqueue と Dequeue を実行するときにロックするだけですか、それとも Count などの値をチェックするときにもロックする必要がありますか?

4

4 に答える 4

3

MSDN から:

Queue<(Of <(T>)>) は、コレクションが変更されない限り、複数のリーダーを同時にサポートできます。それでも、コレクションの列挙は本質的にスレッドセーフな手順ではありません。列挙中のスレッド セーフを保証するために、列挙全体でコレクションをロックできます。読み取りおよび書き込みのために複数のスレッドがコレクションにアクセスできるようにするには、独自の同期を実装する必要があります。

アイテムがキューに入れられている間、リーダーがアクティブになっていないことを確認する必要があります (ロックはおそらく良い考えです)。

リフレクタのカウントを見ると、プライベート フィールドからの読み取りが明らかになります。これは、値をどうするかによっては問題ありません。これは、次のようなことを行うべきではないことを意味します (適切なロックなしで):

if(queue.Count > 0)
    queue.Dequeue();
于 2009-01-10T15:49:12.450 に答える
2

ロックで何をしたいかによって異なります。通常、この種のロックには、リーダー/ライター ロック メカニズムが必要です。

リーダー/ライターのロックとは、リーダーがロックを共有することを意味するため、複数のリーダーがコレクションを同時に読み取ることができますが、書き込むには、排他ロックを取得する必要があります。

于 2009-01-10T15:45:09.243 に答える
1

ロックしないと、古い値を取得する可能性があります。Count を変更して書き込み操作が実行されるなどの競合状態が発生する可能性がありますが、変更の値を取得します。たとえば、キュ​​ーに項目が 1 つしかなく、スレッドが dequeue を呼び出した場合、別のスレッドがカウントを読み取り、まだ 1 であることを確認して、dequeue を再度呼び出すことがあります。2 番目の呼び出しはロックが許可されるまで実行されませんが、その時点でキューは実際には空になります。

于 2009-01-10T15:48:44.867 に答える
0

CLR は、プロセッサの幅までの値のアトミック読み取りを保証します。したがって、32ビットで実行している場合、ints の読み取りはアトミックになります。64 ビット マシンで実行している場合、longs の読み取りはアトミックになります。したがって、 の場合CountInt32ロックする必要はありません。

この投稿はあなたの質問に関連しています。

于 2009-01-10T15:46:44.763 に答える