ネストされたロックが必要な理由を誰かに説明してもらえますか?
この例を見てください:
lock (locker)
lock (locker)
lock (locker)
{
...
}
誰か説明してもらえますか(+例をいただければ幸いです)。
ネストされたロックが必要な理由を誰かに説明してもらえますか?
この例を見てください:
lock (locker)
lock (locker)
lock (locker)
{
...
}
誰か説明してもらえますか(+例をいただければ幸いです)。
ネストされたロックが必要な理由を誰かに説明してもらえますか?
ロックする必要のあるメソッドへのネストされた(たとえば相互再帰的な)呼び出しがある可能性があるため、これは問題にすぎません。これらのメソッドは、リソースがすでにロックされている状態での呼び出しを許可する必要がありますが、リソースに依存することはできません。したがって、ネストされたロックが許可されますが、必要ありません。
あなたが投稿したコード(およびあなたが参照している本)は、それをインラインシナリオに縮小することによってどのように機能するかを示しています。これは「実際の」コードではありません。
単純なルールは、すでにロックを所有しているスレッドが再びロックできることと、ロックを解放するためにExitの数がEnterの数と一致する必要があるということです。
同じスレッドにロックをネストする機能が非常に実用的であるかどうかという状況があります。
複数のメソッドを持つクラスがあるとします。次のような非常に単純なロックスキームが必要だとします。
class A
{
public void MethodOne()
{
using (locker)
{
...body...
}
}
public void MethodTwo()
{
using (locker)
{
...body...
}
}
}
これで、をMethodOne
呼び出すと、モニターに再入可能なロック機能がなかった場合MethodTwo
、最初にデッドロックが発生します。MethodTwo
スレッドは、単にそれ自体をブロックしているはずですlocker
。
幸い、この例は.NETでのみ機能します。ロッカーは、どのスレッドがそれをロックしたか、そして何回かを「知って」おり、所有しているスレッドのみを通過させます。カウントは、他の待機中のスレッドの観点からのロック解除が、終了時MethodOne
ではなく終了時にのみ発生するようにするために使用されMethodTwo
ます。したがって、これは便利なネストされたロックの例です。
一方、質問で言及されている例は、この本から来ているようです。著者は、ネストされたロックが.NETで自動的に可能であることを明確にしたいと考えていました。しかし、それらのサンプルコードは考案されたものであり、内部でロックがどのように機能するかを学習しようとする場合を除いて、誰のコードにも表示されることを意図していません。
あなたの質問に対する直接の答えは、ネストされたロックは必要ないということです。ただし、コンパイラーは、特定のシナリオのコーディングを容易にするためにそれを許可します。
質問のサンプルコードでは、内部ロックは常に成功します。内部ロックに到達するには、外部ロックの取得にすでに成功している必要があるためです。スレッドにはすでにロックがかかっているlocker
ため、内部ロックは「自動的に」成功します。
これは決して必要ではなく、追加のスレッドセーフを提供しません。
ただし、Jirka Hanikaの回答に投稿されているようなシナリオでは、この動作は、デッドロックを心配することなく、あるスレッドセーフメンバーを別のスレッドセーフメンバーから呼び出すことができることを意味します。
あなたが言及するように、ネストされたロックはまったく必要ありません。
ただし、一部のロックはネストできることを明確にするために指摘する価値があります。ReaderWriterLockSlimクラスを確認してください。ここでは、読み取りロックとして入力し、そのスコープ内で、書き込みロックにアップグレードできます。
編集:Royi Namirが指摘しているように、それぞれが独自のロックを持つネストされた関数を呼び出すと、概念的に前述のシナリオが生成されますが、質問が提起される方法では、3つのロックが同じスコープで次々に実行されているように見えます他の意味がありません。