C#での再入可能なロック


119

次のコードは、.NETでC#を使用してデッドロックを引き起こしますか?

 class MyClass
 {
    private object lockObj = new object();

    public void Foo()
    {
        lock(lockObj)
        { 
             Bar();
        }
    }

    public void Bar()
    {
        lock(lockObj)
        { 
          // Do something 
        }
    }       
 }

6
この質問のタイトルを変更することを検討するかもしれません-おそらく最近閉じたようなものにネストされたロックがデッドロックを引き起こさないのはなぜですか?現状では、タイトルはほとんどの場合、人々に発見されないように設計されているようです。
ジェフスターナル

12
実際、これは「reentrant」という検索語に基づいて見つかり、私の質問に答えました。それが
重複

@JeffSternalのコメントに同意します。この質問は、質問を検索する人がすでに「再入可能」ロックに精通していることを前提としています。私が思うに、別の複製の問題。このために良いタイトルを持っていた:stackoverflow.com/questions/3687505/...
ルイス・ペレス

回答:


148

いいえ、同じオブジェクトをロックしている限りは。再帰的コードは事実上すでにロック持っているため妨げられずに続行できます。

lock(object) {...}Monitorクラスを使用するための省略形です。マークが指摘するMonitorことができますリエントラントので、オブジェクトのロックへの試みを繰り返し、現在のスレッドがすでにロック持っている上でうまく動作しますが。

別のオブジェクトでロックを開始する場合は、注意が必要なときです。次の点に特に注意してください。

  • 常に、同じ順序で指定された数のオブジェクトのロックを取得します。
  • ロックは、取得方法とは逆の順序で常に解放してください。

あなたはこれらのルールのいずれかを破る場合はかなりデッドロックの問題を取得することを保証しているいくつかの点で

.NETでのスレッド同期について説明した1つの優れたWebページは次のとおりです。http//dotnetdebug.ne​​t/2005/07/20/monitor-class-avoiding-deadlocks/

また、一度にできるだけ少ない数のオブジェクトをロックします。可能場合は、粗粒度のロックを適用することを検討してください。つまり、オブジェクトグラフが存在するようにコードを記述でき、そのオブジェクトグラフのルートでロックを取得できる場合は、そのようにします。つまり、そのルートオブジェクトにロックが1つあるため、ロックを取得/解放するシーケンスについてそれほど心配する必要はありません。

(もう1つの注意点として、例は技術的に再帰的ではありません。再帰的であるためにはBar()、通常は反復の一部としてそれ自体を呼び出す必要があります。)


1
特に異なるシーケンスで。
Marc Gravell

6
再帰; 確かに; Guyの利益のために、この用語は再入可能です
Marc Gravell

用語の説明に感謝します-質問を編集して修正しました。

この質問はかなり注目を集めているようですので、最初に書いてから思いついた他のいくつかのメモで回答を更新しました。
Neil Barnwell

実際、ロックを解除する順序は重要ではないと思います。それらを選択する順序は間違いなくありますが、ロックの解放が何にも依存しない限り(いつでも解放できます)、獲得したすべてのロックを解放する限り問題ありません。
bobroxsox 2014年

20

まあ、Monitor再入可能にするので、自分でデッドロックすることはできません...だからノー:


7

スレッドがすでにロックを保持している場合、それ自体はブロックされません。.Netフレームワークはこれを保証します。2つのスレッドが同じ2つのロックを任意のコードパスによって順番どおりに取得しようとしないことを確認する必要があるだけです。

同じスレッドは同じロックを複数回取得できますが、取得した回数と同じ回数だけロックを解放する必要があります。もちろん、これを実現するために「lock」キーワードを使用している限り、それは自動的に行われます。


これはモニターに当てはまりますが、必ずしも他の種類のロックではないことに注意してください。
Jon Skeet、

(もちろん、あなたがそれを知らなかったことを意味するつもりはありません。もちろん、それが重要な区別であることだけです。)
Jon Skeet

それは良い点です。私は実際には「ロック」を「モニター」に変更するつもりでしたが、その後気が散りました。そして怠惰。また、この動作はWindowsミューテックスカーネルオブジェクトにも当てはまるため、十分に近いと考えました。
Jeffrey L Whitledge 2008

5

いいえ、このコードにはデッドロックはありません。本当にデッドロックを作成したい場合、最も単純なものは少なくとも2つのリソースを必要とします。犬と骨のシナリオを考えてみましょう。1.犬は1つの骨を完全に制御できるため、他の犬は待つ必要があります。2. 2つの骨を持つ2つの犬は、それぞれの骨をロックして他の骨も探すときにデッドロックを作成するために最低限必要です。

..以下同様に、n個の犬とm個の骨があり、より高度なデッドロックを引き起こします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.