Freigeben über


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. Die Anweisung hat das folgende Format:

Object thisLock = new Object();
lock (thisLock)
{
    // Critical code section.
}

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.

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 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 finden Sie in der C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Siehe auch

Referenz

Threading (C# und Visual Basic)

C#-Schlüsselwörter

Anweisungsschlüsselwörter (C#-Referenz)

MethodImplAttributes

Mutex

Threadsynchronisierung (C# und Visual Basic)

Konzepte

C#-Programmierhandbuch

Monitore

Interlocked-Vorgänge

AutoResetEvent

Weitere Ressourcen

C#-Referenz