Instrução lock (Referência de C#)
A palavra-chave de marca lock um bloco de declaração como uma seção crítica obtendo o bloqueio de mútuo- exclusão para um determinado objeto, executando uma instrução e em seguida, liberando o bloqueio. O exemplo a seguir inclui uma declaração 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 mais informações, consulte Sincronização de thread (C# e Visual Basic).
Comentários
A palavra-chave de lock garante que um segmento não insira uma seção de código crítico quando outro segmento está na seção crítica. Se outro segmento tenta digitar um código bloqueado, esperará, para bloquear, até que o objeto seja liberado.
A seção discute Threading (C# e Visual Basic) segmentação.
A palavra-chave de lock chama Enter no início do bloco e Exit no final do bloco. ThreadInterruptedException é lançada se Interrupt interrompe segmento que está aguardando para inserir uma instrução de lock .
Em geral, evite bloqueio em um tipo de public , ou instâncias além de controle do seu código. Um comum constrói lock (this), lock (typeof (MyType)), e lock ("myLock") viola essa diretriz:
lock (this) é um problema se a instância pode ser acessada publicamente.
lock (typeof (MyType)) é um problema se MyType é publicamente acessível.
lock("myLock") é um problema pois qualquer outro código no processo usando a mesma cadeia de caracteres, compartilhar o mesmo bloqueio.
A prática recomendada é definir em um objeto de private ao bloqueio, ou uma variável de objeto de private static para proteger dados comuns a todas as instâncias.
Você não pode usar a palavra-chave de espere no corpo de uma instrução de lock .
Exemplo
O exemplo a seguir mostra um uso simples de segmentos sem bloqueio em 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
O exemplo a seguir usa segmentos e lock. Como a instrução de lock estiverem presentes, o bloco de declaração é uma seção crítica e balance nunca se tornará um número 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();
}
}
}
Especificação da linguagem C#
Para obter mais informações, consulte a Especificação da linguagem C#. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso de C#.
Consulte também
Referência
Palavras-chave de instrução (Referência de C#)
Sincronização de thread (C# e Visual Basic)