647 Stimmen

Was macht eine Sperrerklärung unter der Haube?

Ich sehe, dass wir bei der Verwendung von Objekten, die nicht thread-sicher sind, den Code mit einer Sperre wie dieser verpacken:

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, er wird in einer ASP.NET-Webanwendung ausgeführt). Stehen sie in einer Warteschlange? Wenn ja, wie lange werden sie warten?

Welche Auswirkungen auf die Leistung hat die Verwendung von Sperren?

536voto

Steven Punkte 157957

El lock Anweisung wird von C# 3.0 wie folgt übersetzt:

var temp = obj;

Monitor.Enter(temp);

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

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

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

Sie können mehr Informationen darüber finden, was Monitor.Enter tut aquí . Um MSDN zu zitieren:

Verwenden Sie Enter zum Erwerb des Monitors am das als Parameter übergebene Objekt. Wenn hat ein anderer Thread einen Enter auf das Objekt, aber noch nicht ausgeführt hat die entsprechende Exit wird der aktuelle Thread wird blockiert, bis der andere Thread das Objekt freigibt. Es ist ist es erlaubt, dass derselbe Thread Enter mehr als einmal, ohne dass es blockiert wird; allerdings wird eine gleiche Anzahl von Exit Aufrufe müssen aufgerufen werden, bevor andere auf das Objekt wartende Threads warten, entblockiert werden.

El Monitor.Enter Methode wird unendlich lange warten; sie wird no Auszeit.

349voto

Umar Abbas Punkte 4299

Es ist einfacher, als Sie denken.

Selon Microsoft : Die lock stellt sicher, dass ein Thread nicht in einen kritischen Abschnitt des Codes eintritt, während sich ein anderer Thread im kritischen Abschnitt befindet. Wenn ein anderer Thread versucht, in einen gesperrten Code einzudringen, wartet er, bis das Objekt freigegeben wird.

El lock Stichwortaufrufe Enter am Anfang des Blocks und Exit am Ende des Blocks. lock Schlüsselwort behandelt eigentlich Monitor Klasse am hinteren Ende.

Zum Beispiel:

private static readonly Object obj = new Object();

lock (obj)
{
    // critical section
}

Im obigen Code tritt der Thread zuerst in einen kritischen Abschnitt ein, und dann wird er gesperrt obj . Wenn ein anderer Thread versucht, einzutreten, wird er ebenfalls versuchen, die obj der bereits durch den ersten Thread gesperrt ist. Der zweite Thread muss auf die Freigabe des ersten Threads warten obj . Wenn der erste Thread geht, wird ein anderer Thread gesperrt obj und wird in den kritischen Bereich eintreten.

58voto

Arsen Mkrtchyan Punkte 48540

Nein, sie stehen nicht in der Warteschlange, sie schlafen.

Eine Sperranweisung der Form

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); }

Man muss nur wissen, dass sie aufeinander warten, und nur ein Thread wird in den Sperrblock eintreten, die anderen werden warten...

Monitor ist vollständig in .net geschrieben, so dass er ausreichend schnell ist, siehe auch Klasse Monitor con Reflektor für weitere Einzelheiten

38voto

Andrew Punkte 5095

Sperren verhindern, dass andere Threads den im Sperrblock enthaltenen Code ausführen. Die Threads müssen warten, bis der Thread innerhalb des Sperrblocks fertig ist und die Sperre aufgehoben wird. Dies hat negative Auswirkungen auf die Leistung in einer Multithreading-Umgebung. 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.

13voto

Simon Woker Punkte 4914

Die Auswirkungen auf die Leistung hängen davon 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 wartenden Code in den Schlaf versetzt. Wenn Sie einige schwere Berechnungen oder lang andauernden Code (z. B. Dateiupload) in einer Sperre haben, führt dies zu einem enormen Leistungsverlust.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X