124

.NET で C# を使用すると、次のコードでデッドロックが発生しますか?

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

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

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

4 に答える 4

156

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

lock(object) {...}Monitorクラスを使用するための省略形です。Marc が指摘しているように、再入Monitor可能であるため、現在のスレッドが既にロックしているオブジェクトを繰り返しロックしようとしても問題なく動作します。

のオブジェクトをロックし始める場合は、注意が必要です。以下に特に注意してください。

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

これらのルールのいずれかを破ると、ある時点でデッドロックの問題が発生することがほぼ保証されます。

.NET でのスレッド同期について説明している 1 つの優れた Web ページを次に示します

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

(さらに注意してください。あなたの例は技術的に再帰的ではありません。再帰的にBar()するには、通常、反復の一部としてそれ自体を呼び出す必要があります。)

于 2008-12-24T17:44:09.733 に答える
21

まあ、Monitor再入を許可するので、自分自身をデッドロックすることはできません...だからいいえ:そうすべきではありません

于 2008-12-24T17:44:42.977 に答える
7

スレッドがすでにロックを保持している場合、それ自体はブロックされません。.Net フレームワークはこれを保証します。コード パスに関係なく、2 つのスレッドが同じ 2 つのロックを順不同で取得しようとしないようにするだけで済みます。

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

于 2008-12-24T18:01:01.213 に答える
5

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

..などn匹の犬とm個の骨など、より洗練されたデッドロックを引き起こします。

于 2012-01-14T18:36:12.160 に答える