2012-05-17 19 views
5

Ich erwarte, dass Sie den folgenden Code in einer Sackgasse, wenn löscht auf das gleiche Objekt zu sperren versucht, die bereits gesperrt Bauen hat:Warum blockiert dieser Code nicht?

void Main() 
{ 
    (new SiteMap()).Build(); 
} 

class SiteMap 
{ 
    private readonly object _lock = new object(); 

    public void Build() 
    { 
     lock (_lock) 
     { 
      Clear(); 

      Console.WriteLine("Build"); 
     } 
    } 

    public void Clear() 
    { 
     lock (_lock) 
     { 
      Console.WriteLine("Clear"); 
     } 
    } 
} 

Ausgang:

Klar

Bauen

Edit 1

Vielen Dank für Ihre Antworten.

Wenn ich einen Anruf hinzufügen im Inneren der Schleuse von Clear (halten den Rest des Codes gleich) Build:

public void Clear() 
{ 
    lock (_lock) 
    { 
     Build(); 

     Console.WriteLine("Clear"); 
    } 
} 

Ein Deadlock auftritt (oder zumindest das ist, was ich denke, LINQ Pad Abstürze).

Laut Ihren Antworten sollte dies nicht passieren, weil es immer noch der gleiche Thread ist.

Danke!

+1

Siehe http://www.albahari.com/threading/part2.aspx, unter "Nested Locking". –

Antwort

8

In C# kann ein Thread, der ein Schloss hält, dasselbe Schloss betreten, ohne zu blockieren.

Die lock Anweisung, sowie die Monitor class, auf der es gebaut wird, ist reentrant in .NET.


bearbeiten als Antwort auf Ihre edit:

Wenn Sie den Anruf Build innen klar hinzufügen, wird der Code nicht Deadlock - es ruft sich selbst rekursiv. Es ist nicht blockiert, sondern läuft immer (bis schließlich Sie eine StackOverflowException getroffen), weil Build Anrufe Clear die Build wieder ruft die Clear nennt, etc ....

+0

In Bezug auf meine Bearbeitung weiß ich wirklich nicht, wie ich das nicht gesehen habe. Danke für beide Antworten! – stacker

4

Ich werde nicht, weil klar innerhalb desselben Threads aufgerufen wird, die bereits die Sperre angewendet.

5

Die Dokumentation für lock sagt:

Wenn ein anderer Thread versucht, einen gesperrten Code einzugeben, wartet (blockiert) er, bis das Objekt freigegeben wird.

Das Schlüsselwort ist "ein anderes". Ein Thread blockiert sich nicht, nur andere Threads. Wenn ein anderer Thread die Sperre besessen hätte, würde lock blockieren.

Dies spart eine Menge Kopfschmerzen.

Verwandte Themen