Istruzione lock (Riferimenti per C#)
Aggiornamento: novembre 2007
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. Tale istruzione assume il seguente formato:
Object thisLock = new Object();
lock (thisLock)
{
// Critical code section.
}
Per ulteriori informazioni, vedere la classe Sincronizzazione di thread (Guida per programmatori C#).
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 (Guida per programmatori C#) vengono fornite informazioni sul threading.
La parola chiave lock chiama Enter all'inizio del blocco e Exit alla fine del blocco.
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.
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 will never be 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 ulteriori informazioni, vedere le sezioni riportate di seguito in Specifiche del linguaggio C#:
5.3.3.18 Istruzioni lock
8.12 Istruzione lock
Vedere anche
Attività
Esempio di tecnologia della sincronizzazione monitor
Esempio di tecnologia della sincronizzazione di attesa
Concetti
Riferimenti
Threading (Guida per programmatori C#)
Parole chiave per le istruzioni (Riferimenti per C#)
Sincronizzazione di thread (Guida per programmatori C#)