Lock Klasse
Definition
Wichtig
Einige Informationen beziehen sich auf Vorabversionen, die vor dem Release ggf. grundlegend überarbeitet werden. Microsoft übernimmt hinsichtlich der hier bereitgestellten Informationen keine Gewährleistungen, seien sie ausdrücklich oder konkludent.
Stellt einen Mechanismus zum Erreichen des gegenseitigen Ausschlusses in Codebereichen zwischen verschiedenen Threads bereit.
public ref class Lock sealed
public sealed class Lock
type Lock = class
Public NotInheritable Class Lock
- Vererbung
-
Lock
Hinweise
Die Lock Klasse kann verwendet werden, um Codebereiche zu definieren, die sich gegenseitig ausschließenden Zugriff zwischen Threads eines Prozesses erfordern, die häufig als kritische Abschnitte bezeichnet werden, um gleichzeitigen Zugriff auf eine Ressource zu verhindern. A Lock kann eingegeben und beendet werden, wobei der Codebereich zwischen Eingabe und Exit ein kritischer Abschnitt ist, der der Sperre zugeordnet ist. Ein Thread, der eine Sperre eingibt, soll die Sperre halten oder besitzen, bis sie die Sperre verlässt. Höchstens ein Thread kann eine Sperre zu einem bestimmten Zeitpunkt halten. Ein Thread kann mehrere Sperren enthalten. Ein Thread kann mehrmals eine Sperre eingeben, bevor er beendet wird, z. B. rekursiv. Ein Thread, der nicht sofort eine Sperre eingeben kann, kann warten, bis die Sperre eingegeben werden kann oder bis ein angegebenes Timeout abläuft.
Wenn Sie die Enter Methoden verwenden, TryEnter um eine Sperre einzugeben:
- Stellen Sie sicher, dass der Thread die Sperre Exit auch bei Ausnahmen beendet, z. B. in C# mithilfe eines
try/finallyBlocks. - Wenn die Sperre in eine C#
async-Methode eingegeben und beendet wird, stellen Sie sicher, dass zwischen Dem Ein- und Beenden keineawaitVorhanden ist. Sperren werden von Threads gehalten, und der Code, der auf einen anderen Thread folgtawait, kann ausgeführt werden.
Es wird empfohlen, die EnterScope Methode mit einem Sprachkonstrukt zu verwenden, das das zurückgegebene Lock.Scope Schlüsselwort wie das C#-Schlüsselwort automatisch verworfen oder das C# usinglock -Schlüsselwort verwendet, da diese sicherstellen, dass die Sperre in Ausnahmefällen beendet wird. Diese Muster haben möglicherweise auch Leistungsvorteile gegenüber der Verwendung Enter/TryEnter und Exit. Das folgende Codefragment veranschaulicht verschiedene Muster zum Eingeben und Beenden einer Sperre.
public sealed class ExampleDataStructure
{
private readonly Lock _lockObj = new();
public void Modify()
{
lock (_lockObj)
{
// Critical section associated with _lockObj
}
using (_lockObj.EnterScope())
{
// Critical section associated with _lockObj
}
_lockObj.Enter();
try
{
// Critical section associated with _lockObj
}
finally { _lockObj.Exit(); }
if (_lockObj.TryEnter())
{
try
{
// Critical section associated with _lockObj
}
finally { _lockObj.Exit(); }
}
}
}
Bei Verwendung des C# lock -Schlüsselworts oder ähnlich zum Eingeben und Beenden einer Sperre muss der Typ des Ausdrucks genau System.Threading.Locksein. Wenn der Typ des Ausdrucks etwas anderes ist, z Object . B. ein generischer Typ wie T, kann stattdessen eine andere Implementierung verwendet werden, die nicht austauschbar ist (z Monitor. B. ). Weitere Informationen finden Sie in den relevanten Compilerspezifikationen.
Interrupt kann Threads unterbrechen, die auf die Eingabe einer Sperre warten. Bei Windows STA-Threads warten, bis Sperren nachrichtenpumpen, die während einer Wartezeit anderen Code im selben Thread ausführen können. Einige Features der Wartezeiten können von einer benutzerdefinierten SynchronizationContextaußer Kraft gesetzt werden.
Note
Ein Thread, der eine Sperre eingibt, einschließlich mehrmals, z. B. rekursiv, muss die Sperre dieselbe Anzahl von Malen beenden, um die Sperre vollständig zu beenden und anderen Threads die Eingabe der Sperre zu ermöglichen. Wenn ein Thread beim Halten eines LockThreads beendet wird, wird das Verhalten der Lock Klammer nicht definiert.
Vorsicht
Wenn in einem Codepfad ein Thread möglicherweise mehrere Sperren eingibt, bevor sie beendet werden, stellen Sie sicher, dass alle Codepfade, die zwei dieser Sperren im selben Thread eingeben können, diese in derselben Reihenfolge eingeben. Andernfalls könnte es zu Deadlocks führen. Denken Sie beispielsweise daran, dass in einem Codepfadthread T1 die Sperre L1 dann gesperrt L2 wird, bevor beide beendet werden, und in einem anderen Codepfadthread T2 werden beide Sperren in umgekehrter Reihenfolge eingegeben. In diesem Szenario wäre es möglich, dass die folgende Reihenfolge von Ereignissen auftritt: Eingaben L1, T2 Eingaben L2, T1 Versucht, einzugeben L2 und zu warten, versucht, T2 einzugeben L1T1 und zu warten. Es gibt ein Deadlock zwischen T1 und T2 das kann nicht aufgelöst werden, und alle anderen Threads, die versuchen, beide Sperren in Zukunft einzugeben, hängen ebenfalls.
Konstruktoren
| Name | Beschreibung |
|---|---|
| Lock() |
Initialisiert eine neue Instanz der Lock-Klasse. |
Eigenschaften
| Name | Beschreibung |
|---|---|
| IsHeldByCurrentThread |
Ruft einen Wert ab, der angibt, ob die Sperre vom aktuellen Thread gehalten wird. |
Methoden
| Name | Beschreibung |
|---|---|
| Enter() |
Wechselt in die Sperre und wartet bei Bedarf, bis die Sperre eingegeben werden kann. |
| EnterScope() |
Wechselt in die Sperre und wartet bei Bedarf, bis die Sperre eingegeben werden kann. |
| Equals(Object) |
Bestimmt, ob das angegebene Objekt dem aktuellen Objekt entspricht. (Geerbt von Object) |
| Exit() |
Beendet die Sperre. |
| GetHashCode() |
Dient als Standardhashfunktion. (Geerbt von Object) |
| GetType() |
Ruft die Type der aktuellen Instanz ab. (Geerbt von Object) |
| MemberwiseClone() |
Erstellt eine flache Kopie der aktuellen Object. (Geerbt von Object) |
| ToString() |
Gibt eine Zeichenfolge zurück, die das aktuelle Objekt darstellt. (Geerbt von Object) |
| TryEnter() |
Versucht, die Sperre einzugeben, ohne zu warten. |
| TryEnter(Int32) |
Versucht, die Sperre einzugeben, und wartet bei Bedarf auf die angegebene Anzahl von Millisekunden, bis die Sperre eingegeben werden kann. |
| TryEnter(TimeSpan) |
Versucht, die Sperre einzugeben, und wartet bei Bedarf, bis die Sperre eingegeben werden kann oder bis das angegebene Timeout abläuft. |