lock-Anweisung (C#-Referenz)

Das Schlüsselwort lock kennzeichnet einen Anweisungsblock als kritischen Abschnitt, indem es die sich gegenseitig ausschließende Sperre für ein gegebenes Objekt abruft, eine Anweisung ausführt und anschließend die Sperre aufhebt. 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.

Hinweise

Das Schlüsselwort lock stellt sicher, dass ein Thread keinen kritischen Abschnitt eines Codes betritt, während ein anderer Thread in diesem Abschnitt ist. Wenn ein anderer Thread versucht, auf einen gesperrten Code zuzugreifen, wartet er, sperrt, bis das Objekt freigegeben wird.

Der Abschnitt Threading wird das Threading behandeln.

Das lock-Schlüsselwort ruft am Anfang des Blocks Enter und am Ende des Blocks Exit auf. Ein ThreadInterruptedException wird ausgelöst, wenn Interrupt einen Thread unterbricht, der darauf wartet eine lock-Anweisung einzugeben.

Vermeiden Sie generell das Sperren eines public-Typs oder von Instanzen außerhalb der Kontrolle Ihres Codes. Die gemeinsamen Konstrukte lock (this), lock (typeof (MyType)) und lock ("myLock") verstoßen gegen diese Richtlinie:

  • lock (this) ist ein Problem, wenn auf die Instanz öffentlich zugegriffen werden kann.

  • lock (typeof (MyType)) ist problematisch, wenn auf MyType öffentlich zugegriffen werden.

  • lock("myLock") ist problematisch, weil jeder andere Code in diesem Prozess, der die selbe Zeichenfolge verwendet, die gleiche Sperre teilt.

Eine bewährte Methode ist es, ein private-Objekt zum Sperren, oder eine private static-Objektvariable zu definieren, die Daten schützt, die in allen Instanzen häufig vorkommen.

Sie können das Schlüsselwort await nicht im Text einer lock-Anweisung verwenden.

Beispiel

Im folgenden Beispiel wird eine einfache Verwendung von Threads ohne das Sperren in C# gezeigt.

//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

Beispiel

Im folgenden Beispiel werden Threads und lock verwendet. Solange die lock-Anweisung vorhanden ist, ist der Anweisungsblock ein kritischer Abschnitt, und balance wird nie eine negative Zahl werden.

// 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();
        }
        
        //block main thread until all other threads have ran to completion.
        foreach (var t in threads)
            t.Join();
    }
}

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

MethodImplAttributes
Mutex
C#-Referenz
C#-Programmierhandbuch
Threading
C#-Schlüsselwörter
Anweisungsschlüsselwörter
Monitor
Interlocked-Vorgänge
AutoResetEvent
Threadsynchronisierung