Condividi tramite


Istruzione lock (Riferimenti per C#)

La parola chiave lock contrassegna un blocco di istruzioni come sezione critica ottenendo il blocco a esclusione reciproca per un determinato oggetto, eseguendo un'istruzione e rilasciando in seguito il blocco. L'esempio seguente illustra un'istruzione 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;
            }
        }
    }

Per ulteriori informazioni, vedere Sincronizzazione di thread (C# e Visual Basic).

Note

La parola chiave lock impedisce a un thread di entrare in una sezione critica del codice se è già presente un altro thread. Se un altro thread tenta di accedere a un codice bloccato, attenderà (in stato di blocco) finché l'oggetto non verrà rilasciato.

Nella sezione Threading (C# e Visual Basic) vengono fornite informazioni sul threading.

La parola chiave lock chiama Enter all'inizio del blocco e Exit alla fine del blocco. ThreadInterruptedException viene generato se Interrupt interrompere un thread in attesa di per immettere un'istruzione lock.

In generale è opportuno evitare il blocco su un tipo public o su istanze oltre il controllo del codice. I costrutti comuni lock (this), lock (typeof (MyType)) e lock ("myLock") non rispettano questa regola:

  • lock (this) costituisce un problema se l'accesso all'istanza può avvenire pubblicamente.

  • lock (typeof (MyType)) costituisce un problema se l'accesso a MyType può avvenire pubblicamente.

  • lock("myLock") costituisce un problema poiché qualsiasi altro codice nel processo che utilizza la stessa stringa condividerà lo stesso blocco.

La procedura migliore consiste nel definire un oggetto private da bloccare o una variabile oggetto private static per proteggere i dati comuni a tutte le istanze.

Non è possibile utilizzare la parola chiave attendere nel corpo di un'istruzione lock.

Esempio

Nell'esempio seguente viene illustrato un utilizzo semplificato dei thread senza blocco in 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

Nell'esempio riportato di seguito vengono utilizzati thread e lock. Finché l'istruzione lock è presente, il blocco di istruzioni rimarrà una sezione critica e balance non diventerà mai un numero 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();
            }
        }
    }

Specifiche del linguaggio C#

Per altre informazioni, vedere la Specifiche del linguaggio C#. La specifica del linguaggio costituisce il riferimento ufficiale principale per la sintassi e l'uso di C#.

Vedere anche

Riferimenti

Parole chiave di C#

Parole chiave per le istruzioni (Riferimenti per C#)

MethodImplAttributes

Mutex

Sincronizzazione di thread (C# e Visual Basic)

Concetti

Guida per programmatori C#

Monitor

Operazioni interlocked

AutoResetEvent

Altre risorse

Riferimenti per C#

Threading (C# e Visual Basic)