lock-Anweisung (C#-Referenz)
Aktualisiert: November 2007
Das lock-Schlüsselwort kennzeichnet einen Anweisungsblock als kritischen Abschnitt, indem die Sperre für gegenseitigen Ausschluss eines bestimmten Objekts ermittelt, eine Anweisung ausgeführt und die Sperre wieder aufgehoben wird. Die Anweisung hat das folgende Format:
Object thisLock = new Object();
lock (thisLock)
{
// Critical code section.
}
Weitere Informationen hierzu finden Sie unter Threadsynchronisierung (C#-Programmierhandbuch).
Hinweise
Mit dem lock-Schlüsselwort wird sichergestellt, dass ein Thread nicht auf einen kritischen Abschnitt des Codes zugreift, während ein anderer Thread mit diesem Codeabschnitt befasst ist. Wenn ein anderer Thread versucht, auf gesperrten Code zuzugreifen, wartet er bis zur Freigabe des Objekts (Blockierung).
Im Abschnitt Threading (C#-Programmierhandbuch) wird das Threading beschrieben.
Das lock-Schlüsselwort ruft Enter am Anfang des Blocks und Exit am Ende des Blocks auf.
Vermeiden Sie es grundsätzlich, einen public-Typ zu sperren oder Instanzen, die nicht durch Ihren Code gesteuert werden. Die allgemeinen Konstrukte lock (this), lock (typeof (MyType)) und lock ("myLock") verstoßen gegen diese Richtlinie:
lock (this) ist problematisch, wenn auf die Instanz öffentlich zugegriffen werden kann.
lock (typeof (MyType)) ist problematisch, wenn MyType öffentlich zugreifbar ist.
lock(“myLock”) ist problematisch, weil jeder andere Code in diesem Prozess, der dieselbe Zeichenfolge verwendet, von derselben Sperre betroffen ist.
Es wird empfohlen, ein private-Objekt zu definieren, das gesperrt werden soll, oder eine private static-Objektvariable, um Daten zu schützen, die alle Instanzen gemeinsam nutzen.
Beispiel
Im folgenden Beispiel wird eine einfache Verwendung von Threads ohne Sperren in C# dargestellt:
//using System.Threading;
class ThreadTest
{
public void RunMe()
{
Console.WriteLine("RunMe called");
}
static void Main()
{
ThreadTest b = new ThreadTest();
Thread t = new Thread(b.RunMe);
t.Start();
}
}
// Output: RunMe called
Im folgenden Beispiel werden Threads und lock verwendet. Solange die lock-Anweisung vorhanden ist, stellt der Anweisungsblock einen kritischen Abschnitt dar, und balance wird nie zu einer negativen Zahl.
// using System.Threading;
class Account
{
private Object thisLock = new Object();
int balance;
Random r = new Random();
public Account(int initial)
{
balance = initial;
}
int Withdraw(int amount)
{
// This condition will never be true unless the lock statement
// is commented out:
if (balance < 0)
{
throw new Exception("Negative Balance");
}
// Comment out the next line to see the effect of leaving out
// the lock keyword:
lock (thisLock)
{
if (balance >= amount)
{
Console.WriteLine("Balance before Withdrawal : " + balance);
Console.WriteLine("Amount to Withdraw : -" + amount);
balance = balance - amount;
Console.WriteLine("Balance after Withdrawal : " + balance);
return amount;
}
else
{
return 0; // transaction rejected
}
}
}
public void DoTransactions()
{
for (int i = 0; i < 100; i++)
{
Withdraw(r.Next(1, 100));
}
}
}
class Test
{
static void Main()
{
Thread[] threads = new Thread[10];
Account acc = new Account(1000);
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}
}
}
C#-Programmiersprachenspezifikation
Weitere Informationen finden Sie in den folgenden Abschnitten von C#-Programmiersprachenspezifikation:
5.3.3.18 lock-Anweisungen
8.12 Die lock-Anweisung
Siehe auch
Aufgaben
Technologiebeispiel für Monitor-Synchronisierung
Technologiebeispiel für Wait-Synchronisierung
Konzepte
Referenz
Threading (C#-Programmierhandbuch)
Anweisungsschlüsselwörter (C#-Referenz)
Threadsynchronisierung (C#-Programmierhandbuch)