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 per le istruzioni (Riferimenti per C#)
Sincronizzazione di thread (C# e Visual Basic)