2009-01-30 4 views
5

In Release It! begründet Michael Nygard, dass viele katastrophale Systemausfälle oft durch eine Kette von Dingen verursacht werden, die schief gehen. Zum Beispiel, zwei Threads Deadlock. Es gibt jetzt zwei weniger Threads im Thread-Pool, so dass die Last bei den anderen Threads steigt und die Wahrscheinlichkeit von Deadlocks steigt. Plötzlich reagiert der Server überhaupt nicht mehr, weil der Thread-Pool erschöpft ist, was dazu führt, dass der Lastenausgleich den Datenverkehr auf die anderen Server umleitet (die alle den gleichen Code ausführen), was die Wahrscheinlichkeit von Deadlocks erhöht. Plötzlich ist die ganze Farm offline.Sollten Sie Timeouts für Sperren in .NET anfordern?

Die meisten RDBMS-Server erkennen Deadlocks und entscheiden über einen "Verlierer" (eine Transaktion wird abgebrochen, die andere kann fortfahren). Im Gegensatz dazu wird in C# die Sperre Anweisung unbegrenzt auf eine Sperre warten, die erworben werden soll.

Sie können jedoch Monitor.TryEnter(lockObject, TimeSpan) anrufen, um eine Sperre oder Timeout anzufordern. Es gibt false zurück, wenn das Zeitlimit abgelaufen ist und die Sperre nicht erlangt werden konnte. Einige haben wrapped this in using statements, um eine nette Syntax zu behalten.

Also meine Frage ist, erhalten Sie immer Sperren mit Timeouts, oder nicht? Und welche Probleme verursachen Zeitüberschreitungen im Vergleich zu einem Deadlock-Szenario?

Antwort

5

Ich verwende normalerweise Timeouts. Das größte Problem hierbei ist, dass die anfordernde Operation abgebrochen wird, wenn die Zeitüberschreitung erreicht ist. Dies ist offensichtlich dem Stillstand vorzuziehen. Es gibt jedoch ein größeres Problem: Wenn die Operation kritisch ist und Sie abbrechen, weil etwas anderes festgefahren ist, könnten Sie, wenn Ihr Design nicht fehlerfrei ist, das Problem verursachen, das Sie mit dieser Methode beschrieben haben (allerdings weicher: Ihre App wird nicht mehr funktionieren, aber Sie haben die Kontrolle nicht verloren).

Der Hauptunterschied besteht darin, dass Sie hier tatsächlich die Kontrolle haben. Wenn Threads mit dem Deadlock beginnen, können Sie nichts tun, um das Problem zu beheben, sobald der Fehler aufgetreten ist.

1

Als allgemeine Regel I nie Sperren mit unbegrenzten Timeouts erstellen. Es führt einfach zu schwer zu findenden und schwer zu debuggenden Deadlocks. Es braucht keine zusätzliche Arbeit, um eine Zeitüberschreitungsprüfung hinzuzufügen, auch wenn es nur eine Ausnahme auslöst, und es benachrichtigt Sie fast sofort, wenn Sie einen Deadlock haben. Noch wichtiger ist, dass es hilft, Engpässe zu finden, die durch bu-Sperren verursacht werden, die möglicherweise keine vollständigen Deadlocks verursachen.

0

Es ist möglich zu beweisen, dass Deadlocks nicht auftreten können. Es ist auch möglich, zur Laufzeit zu beweisen, dass Deadlocks auch ohne Abhängigkeit von Rennbedingungen auftreten können (siehe z. B. Linux).

Daher immer versuchen, ein Schloss macht keinen Sinn. Es hängt von den Umständen ab.

1

Können Sie die Situation, in der der Sperrversuch abgelaufen ist, ordnungsgemäß wiederherstellen? Wenn Sie können dann Timeouts auf alle Fälle verwenden. Wenn Sie nicht können, dann gibt es nicht viel Sinn beim Zeitablauf. Was werden Sie tun, wenn Sie die Ausführung fortsetzen? Am besten können Sie mit einer Fehlermeldung beenden. Timeouts haben ihren Nutzen, aber sie können auch dazu verwendet werden, um versteckte Threading-Bugs zu verstecken, daher denke ich, dass der beste Rat mit Vorsicht zu gebrauchen ist.

+0

Ich denke, die Frage wird, wenn alles, was Sie tun können, eine Fehlermeldung zeigt, ist das besser als unendlich warten? Deadlocks geben Ihnen keine Möglichkeit zum Rollback, und Fehler sind wahrscheinlich eine (geringfügig) bessere Benutzererfahrung als eine eingefrorene Anwendung. –

Verwandte Themen