lock-Anweisung (C#-Referenz)
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. Das folgende Beispiel enthält eine lock-Anweisung.
class Account
{
decimal balance;
private Object thisLock = new Object();
public void Withdraw(decimal amount)
{
lock (thisLock)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
Weitere Informationen finden Sie unter Threadsynchronisierung (C# und Visual Basic).
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# und Visual Basic) wird das Threading beschrieben.
Das lock-Schlüsselwort ruft Enter am Anfang des Blocks und Exit am Ende des Blocks auf. ThreadInterruptedException wird ausgelöst, wenn Interrupt einen Thread unterbrochen wird, der wartet, eine lock-Anweisung einzugeben.
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.
Sie können das Sie erwarten-Schlüsselwort im Text einer lock-Anweisung verwenden.
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 never is 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 erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.
Siehe auch
Referenz
Anweisungsschlüsselwörter (C#-Referenz)
Threadsynchronisierung (C# und Visual Basic)