lock
2 つ (またはそれ以上) の異なるオブジェクトで使用するための構文は次のとおりです。
lock (a) lock (b)
{
}
ただし、このタイプの使用は一般的にお勧めできません。これにはいくつかの理由があります。
- ロックが宣言される順序は、どこでも一貫していなければなりません。そうしないと、デッドロックが発生する可能性があります。
- ほとんどの場合、不要です。
- コード臭です。
私の意見では、最初の理由は本当に警官です。開発中にミスを犯す可能性のある方法は無数にあります。これは数ある中の 1 つにすぎません。そして、実際には、(起こりうる他の種類の間違いと比較して) 正しいことをするのは非常に簡単です。ロックが常に同じ順序で取得されるようにしてください。さらに、ネストされたロックを使用することについて、本質的に危険なことは何もありません (これも、正しく行われている限り)。ネストされたロックは常に取得されます。ほとんどの場合、他のクラスを呼び出すことによって、または実行がさまざまなスタック フレームを介して進行するときに、暗黙的に行われます。
ここで本当に重要なのは、2 番目と 3 番目の理由です。ほとんどの場合、1 つのロックで十分であるため、コードの同じセクションで 2 つのロックを取得する必要はありません。実際、コードの同じセクションで 2 つのロックを取得する必要があったとは思いません。少なくとも明示的ではありません。それは通常、問題について間違って考えていることを意味するため、コードの匂いです。コードが複雑であるか、奇妙なコード パスを使用している可能性があります。必要なロックが 1 つだけになるようにコードを構造化すると、コードの追跡がはるかに容易になる可能性があります。
別のメモとして、ロックがどのように機能するかについて混乱しているのではないかと思います. キーワードで使用されているオブジェクト インスタンスlock
が同時アクセスから保護されていると考えているなら、それは間違いです。それはlock
キーワードの仕組みではありません。によって参照されるオブジェクトは、同じオブジェクト参照lock
でマークされた別の (または同じ) セクションと同時に実行されないことが保証されているコードのクリティカル セクションをマークすることを目的としています。
アップデート:
私はあなたの例を見て、最初に飛び出したのは、このコードがスレッドセーフではないかもしれないということです. ただし、関連する完全なコンテキストはわかりません。私が見ているのは、この架空のクラスが内部で 2 つのキューを使用しており、2 つの異なるロックをパルスしているということだけです。ある程度の推測はできますが、間違っているかもしれません。単一のクラス内でそのようなことを行う状況を想像するのに苦労しています。しかし、そうは言っても、このコードを実行するスレッドがロック間でプリエンプトされるとどうなるか考えたことはありますか? これは、クラスが中途半端な状態になるチャンスです (アイテムはどちらのキューにもありません)。別のスレッドがこのクラスを使用しようとするとどうなりますか? アイテムがぶら下がっている状況をうまく処理できますか? さらにコメントするには、さらに多くのコードを確認する必要があります。