57

重複の可能性:
C#での再入可能ロック

このようなコードを書くと:

class Program {
    static void Main(string[] args) {
        Foo();
        Console.ReadLine();
    }

    static void Foo() {
        lock(_lock) {
            Console.WriteLine("Foo");
            Bar();
        }
    }

    static void Bar() {
        lock(_lock) {
            Console.WriteLine("Bar");
        }
    }

    private static readonly object _lock = new object();
}

私は出力として取得します:

Foo
Bar

Fooがロックを取得し、Barがロックを取得するのを待つため、これがデッドロックになると予想しました。しかし、これは起こりません。

コードが同じスレッドで実行されるため、ロックメカニズムは単にこれを許可しますか?

4

4 に答える 4

87

同じスレッドの場合、ロックは常に再入可能であるため、スレッドはオブジェクトを何度でもロックできます。

于 2012-10-22T18:18:35.493 に答える
22

ここにはスレッドが 1 つしかないためです。

lockのショートカットです

bool lockWasTaken = false;
var temp = obj;
try { 
       Monitor.Enter(temp, ref lockWasTaken); 
       // your thread safe code
}
finally { if (lockWasTaken) Monitor.Exit(temp); }

Monitor.Enterは、パラメータとして渡されたオブジェクトの Monitor を取得します。別のスレッドがオブジェクトに対して Enter を実行したが、対応する Exit をまだ実行していない場合、現在のスレッドは、別のスレッドがオブジェクトを解放するまでブロックされます。同じスレッドが Enter をブロックせずに複数回呼び出すことは合法です。ただし、オブジェクトを待機している他のスレッドがブロックを解除する前に、同数の Exit 呼び出しを呼び出す必要があります。

于 2012-10-22T18:18:26.100 に答える
10

一言:リエントラントロック。スレッドがすでにロックを取得している場合、ロックを再度取得するかどうかは待機しません。これは非常に必要です。そうでなければ、単純な再帰関数が悪夢に変わる可能性があります。

于 2012-10-22T18:37:50.277 に答える
5

ステートメントはそれlockよりもスマートで、これを防ぐように設計されています。ロックは、スレッドが内部に入るとスレッドによって「所有」されるためlock、同じオブジェクトをロックする別のステートメントに到達すると、そのロックへのアクセスが既にあることがわかります。

于 2012-10-22T18:19:24.640 に答える