このlock
ステートメントは、相互排除の概念を紹介しています。特定のオブジェクトのロックを一度に取得できるのは1つのスレッドだけです。これにより、スレッドが共有データ構造に同時にアクセスして、それらが破損するのを防ぎます。
他のスレッドがすでにロックを保持している場合、lockステートメントは、引数の排他ロックを取得できるようになるまでブロックしてから、ブロックの実行を許可します。
lock
唯一のことは、コードのブロックへのエントリを制御することであることに注意してください。クラスのメンバーへのアクセスは、ロックとはまったく関係ありません。lock
同期する必要のあるアクセスが、または他の同期プリミティブを使用して調整されるようにするのは、クラス自体の責任です。また、一部またはすべてのメンバーへのアクセスを同期する必要がない場合があることにも注意してください。たとえば、カウンターを維持したい場合は、ロックせずにInterlockedクラスを使用できます。
ロックの代わりに、ロックフリーのデータ構造があります。これは、複数のスレッドが存在する場合に正しく動作します。ロックフリーデータ構造の操作は、通常、コンペアアンドスワップ(CAS)などのロックフリープリミティブを使用して、非常に慎重に設計する必要があります。
このような手法の一般的なテーマは、データ構造に対してアトミックに操作を実行し、他のスレッドによる同時アクションとそれに続く再試行が原因で操作が失敗したことを検出することです。これは、障害が発生する可能性が低い軽負荷のシステムではうまく機能しますが、障害率が上昇して再試行が主要な負荷になると、暴走動作を引き起こす可能性があります。この問題は、再試行率を下げて負荷を効果的に抑えることで改善できます。
より洗練された代替手段は、ソフトウェアトランザクショナルメモリです。CASとは異なり、STMは失敗と再試行の概念を任意に複雑なメモリ操作に一般化します。簡単に言うと、トランザクションを開始し、すべての操作を実行して、最後にコミットします。システムは、現在のスレッドをパンチに打ち負かす他のスレッドによって実行される操作の競合が原因で操作が成功しないかどうかを検出します。このような場合、STMは完全に失敗し、アプリケーションに修正措置を講じる必要があります。または、より高度な実装では、STMは自動的にトランザクションの開始に戻り、再試行できます。