it-swarm.com.de

Wie funktioniert das Schloss genau?

Ich sehe, dass wir für die Verwendung von Objekten, die nicht threadsicher sind, den Code mit einer Sperre wie folgt umschließen:

private static readonly Object obj = new Object();

lock (obj)
{
    // thread unsafe code
}

Was passiert also, wenn mehrere Threads auf denselben Code zugreifen (nehmen wir an, dass er in einer ASP.NET-Webanwendung ausgeführt wird)? Stehen sie in der Warteschlange? Wenn ja, wie lange werden sie warten?

Wie wirkt sich die Verwendung von Sperren auf die Leistung aus?

465
NLV

Die lock -Anweisung wird von C # 3.0 folgendermaßen übersetzt:

var temp = obj;

Monitor.Enter(temp);

try
{
    // body
}
finally
{
    Monitor.Exit(temp);
}

In C # 4.0 dies hat sich geändert und es wird nun wie folgt generiert:

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

Weitere Informationen zu den Funktionen von Monitor.Enter finden Sie hier . So zitieren Sie MSDN:

Verwenden Sie Enter, um den Monitor für das als Parameter übergebene Objekt abzurufen. Wenn ein anderer Thread ein Enter für das Objekt ausgeführt hat, aber noch nicht das entsprechende Exit ausgeführt hat, wird der aktuelle Thread blockiert, bis der andere Thread das Objekt freigibt. Es ist zulässig, dass derselbe Thread Enter mehr als einmal aufruft, ohne dass er blockiert. Es muss jedoch die gleiche Anzahl von Exit Aufrufen aufgerufen werden, bevor andere auf das Objekt wartende Threads die Blockierung aufheben.

Die Monitor.Enter Methode wird unendlich warten; es wird keine Zeitüberschreitung geben.

411
Steven

Es ist einfacher als Sie denken.

Laut Microsoft : Das Schlüsselwort lock stellt sicher, dass ein Thread keinen kritischen Codeabschnitt eingibt, während sich ein anderer Thread im kritischen Abschnitt befindet. Wenn ein anderer Thread versucht, einen gesperrten Code einzugeben, wartet er blockiert, bis das Objekt freigegeben wird.

Das Schlüsselwort lock ruft am Anfang des Blocks Enter und am Ende des Blocks Exit auf. Das Schlüsselwort lock behandelt tatsächlich die Klasse Monitor am Back-End.

Zum Beispiel:

private static readonly Object obj = new Object();

lock (obj)
{
    // critical section
}

Im obigen Code gibt der Thread zuerst einen kritischen Abschnitt ein und sperrt dann obj. Wenn ein anderer Thread versucht einzutreten, wird auch versucht, obj zu sperren, der bereits vom ersten Thread gesperrt ist. Ich muss warten, bis der erste Thread obj veröffentlicht hat. Wenn der erste Thread verlässt, wird ein anderer Thread obj sperren und den kritischen Abschnitt betreten.

243
Umar Abbas

Nein, sie stehen nicht in der Warteschlange, sie schlafen

Eine Sperranweisung des Formulars

lock (x) ... 

wobei x ein Ausdruck eines Referenztyps ist, ist genau äquivalent zu

var temp = x;
System.Threading.Monitor.Enter(temp); 
try { ... } 
finally { System.Threading.Monitor.Exit(temp); }

Sie müssen nur wissen, dass sie aufeinander warten und nur ein Thread zum Sperren des Blocks eingeht, die anderen warten ...

Monitor ist vollständig in .net geschrieben, daher ist es schnell genug. Weitere Informationen finden Sie unter Klasse Monitor mit Reflektor

43
Arsen Mkrtchyan

Sperren verhindern, dass andere Threads den im Sperrblock enthaltenen Code ausführen. Die Threads müssen warten, bis der Thread im Sperrblock abgeschlossen und die Sperre aufgehoben ist. Dies wirkt sich negativ auf die Leistung in einer Multithread-Umgebung aus. Wenn Sie dies tun müssen, sollten Sie sicherstellen, dass der Code innerhalb des Sperrblocks sehr schnell verarbeitet werden kann. Sie sollten versuchen, teure Aktivitäten wie den Zugriff auf eine Datenbank usw. zu vermeiden.

26
Andrew

Die Auswirkungen auf die Leistung hängen von der Art und Weise ab, wie Sie sperren. Eine gute Liste von Optimierungen finden Sie hier: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/ =

Grundsätzlich sollten Sie versuchen, so wenig wie möglich zu sperren, da dies Ihren Wartecode in den Ruhezustand versetzt. Wenn Sie einige schwere Berechnungen oder lang anhaltenden Code (z. B. Datei-Upload) in einer Sperre haben, führt dies zu einem enormen Leistungsverlust.

10
Simon Woker

Der Teil innerhalb der lock-Anweisung kann nur von einem Thread ausgeführt werden, sodass alle anderen Threads auf unbestimmte Zeit darauf warten, dass der Thread, der die Sperre hält, beendet wird. Dies kann zu einem sogenannten Deadlock führen.

7
Mr47

Die Anweisung lock wird in Aufrufe der Methoden Enter und Exit von Monitor übersetzt.

Die Anweisung lock wartet auf unbestimmte Zeit, bis das Sperrobjekt freigegeben wird.

7
Paolo Tedesco

lock ist eigentlich versteckt Monitor Klasse.

4
Euphoric