lock (Instrucción, Referencia de C#)

La palabra clave lock marca un bloque de instrucciones como una sección crucial, para lo cual utiliza el bloqueo de exclusión mutua de un objeto, la ejecución de una instrucción y, posteriormente, la liberación del bloqueo. El ejemplo siguiente incluye un fragmento de lock .

    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;
            }
        }
    }

Para obtener más información, vea Sincronización de subprocesos (C# y Visual Basic).

Comentarios

La palabra clave lock garantiza que un subproceso no va a entrar en una sección crítica del código mientras otro subproceso se encuentre ya en esta sección. Si otro subproceso intenta entrar en un código bloqueado, esperará, o se bloqueará, hasta que el objeto se libere.

En la sección Subprocesamiento (C# y Visual Basic) se describe el subprocesamiento.

La palabra clave lock llama a Enter al principio del bloque y a Exit al final del bloque. Se produce ThreadInterruptedException si Interrupt interrumpe un subproceso que está esperando para escribir un fragmento de lock .

En general evite bloquear un tipo public o instancias que estén fuera del control de su código. Las construcciones comunes lock (this), lock (typeof (MyType)) y lock ("myLock") incumplen esta instrucción:

  • lock (this) se convierte en un problema si la instancia es accesible públicamente.

  • lock (typeof (MyType)) se convierte en un problema si MyType es accesible públicamente.

  • lock("myLock") se convierte en un problema puesto que cualquier otro código del proceso que utilice la misma cadena compartirá el mismo bloqueo.

El procedimiento recomendado es definir un objeto un objeto private para realizar el bloqueo o una variable de objeto private static para proteger los datos comunes a todas las instancias.

No puede utilizar la palabra clave de espera en el cuerpo de un fragmento de lock .

Ejemplo

El siguiente ejemplo muestra un uso simple de subprocesos sin bloquear en C#.

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

El siguiente ejemplo utiliza subprocesos y lock. Con el uso de la instrucción lock, el bloque de instrucciones se convierte en una sección crítica y balance nunca tomará un valor negativo.

    // 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();
            }
        }
    }

Especificación del lenguaje C#

Para obtener más información, consulte la Especificación del lenguaje C#. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.

Vea también

Referencia

Palabras clave de C#

Palabras clave de instrucciones (Referencia de C#)

MethodImplAttributes

Mutex

Sincronización de subprocesos (C# y Visual Basic)

Conceptos

Guía de programación de C#

Monitores

Operaciones de bloqueo

AutoResetEvent

Otros recursos

Referencia de C#

Subprocesamiento (C# y Visual Basic)