ロックの再帰とは、元のロックを離れることなく、同じスレッドで同じロックを複数回取得することを指します。
これに関する主な問題は、そもそもそのような状況に陥るには、必要な同期を処理する人に深刻な問題がある可能性があることです。ロックが細かすぎるか、グローバルすぎる可能性があります。マルチスレッド化は難しく、それをさらに難しくするのはまったくのばかげたことです。
2 つ目の重要な点は、ロックがスレッドに関連付けられていることです。ただし、非同期コードを記述している場合、コードが異なるスレッド間を意地悪にジャンプしている可能性があります。これは、再帰ロックを取得しているように見えるコードがそうではないことを意味する場合があります。外側のロックは、別のスレッドによって所有されることになります。内側のロックよりも、スレッド A がスレッド B の終了を待っている間、スレッド B が A が外側のロックを解放するのを待っている状態で、永遠にデッドロック状態になります。
ReaderWriterLockSlim
再帰が有効になっている場合でも、多くの再帰例外がスローされると述べました。はい、これは、再帰ロックを使用する方が、 egReaderWriterLock
またはを処理する場合よりも少し安全であることを意味しMonitor
ます。ルールは MSDN で明確に概説されています。
再帰を許可する ReaderWriterLockSlim の場合、スレッドが入ることができるモードについて次のことが言えます。
- 読み取りモードのスレッドは、再帰的に読み取りモードに入ることができますが、書き込みモードまたはアップグレード可能モードに入ることはできません。これを行おうとすると、LockRecursionException がスローされます。読み取りモードに入ってから書き込みモードまたはアップグレード可能モードに入るのは、デッドロックの可能性が高いパターンであるため、許可されません。前述のように、ロックをアップグレードする必要がある場合には、アップグレード可能モードが提供されます。
- アップグレード可能モードのスレッドは、書き込みモードおよび/または読み取りモードに入ることができ、3 つのモードのいずれにも再帰的に入ることができます。ただし、読み取りモードのスレッドが他にある場合、書き込みモードに入ろうとするとブロックされます。
- 書き込みモードのスレッドは、読み取りモードおよび/またはアップグレード可能モードに入ることができ、3 つのモードのいずれにも再帰的に入ることができます。
- ロックに入っていないスレッドは、どのモードにも入ることができます。この試行は、非再帰的なロックに入ろうとするのと同じ理由でブロックされる可能性があります。
スレッドは、そのモードに入った回数と正確に同じ回数だけ各モードを終了する限り、開始したモードを任意の順序で終了できます。スレッドがモードを何度も終了しようとした場合、またはモードに入っていないモードを終了しようとした場合は、SynchronizationLockException がスローされます。
彼らは、デッドロックを引き起こすことがほぼ保証されている再帰を完全に禁止するために最善を尽くしました。ただし、これは、見過ごされているデッドロックがまだないという意味ではありません (結局のところ、デッドロックを引き起こすために再帰は必要ありません。デッドロックの機会を見つけるのが難しいだけです)。定期的にロックを再帰するコードで一貫性の保証を行うのはかなり難しいことは言うまでもありません。これは、一部の操作が外部ロックから呼び出されると (半) 原子的であるが、直接呼び出されると停止することを意味する場合があります。
マルチスレッドはそのままでは十分に難しいです。オブジェクト設計が壊れているからといって、さらに難しくしないでください :) マルチスレッド (一般的に、特に .NET) の優れた入門書は、インターネットで無料で入手できる Joe Albahari の「Threading in C#」です (感謝します)。 、ジョー!)。ReaderWriterLockSlim
特にhttp://www.albahari.com/threading/part4.aspx#_Reader_Writer_Locksで処理されます