Оператор lock (Справочник по C#)
При помощи ключевого слова lock блок операторов можно пометить как важный фрагмент, получив блокировку взаимного исключения для указанного объекта, выполнив оператор, а затем сняв блокировку.Следующий пример включает 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;
}
}
}
Дополнительные сведения см. в разделе Синхронизация потоков (C# и Visual Basic).
Заметки
Ключевое слово lock не позволит одному потоку войти в важный раздел кода в тот момент, когда в нем находится другой поток.При попытке входа другого потока в заблокированный код потребуется дождаться снятия блокировки объекта.
Работа с потоками описана в разделе Работа с потоками (C# и Visual Basic).
Ключевое слово lock вызывает Enter в начале блока и Exit в конце блока.ThreadInterruptedException возникает, если Interrupt прерывает поток, который ожидает входа в выписку lock.
Как правило, рекомендуется избегать блокировки типа public или экземпляров, которыми код не управляет.Распространенные конструкторы lock (this), lock (typeof (MyType)) и lock ("myLock") не соблюдают это правило.
lock (this) может привести к проблеме, если к экземпляру допускается открытый доступ.
lock (typeof (MyType)) может привести к проблеме, если к MyType допускается открытый доступ.
lock("myLock") может привести к проблеме, поскольку любой код в процессе, используя ту же строку, будет совместно использовать ту же блокировку.
Для блокировки рекомендуется определять объект private или переменную объекта private static, чтобы защитить данные, являющиеся общими для всех экземпляров.
Нельзя использовать ключевое слово подождите в теле выписки lock.
Пример
В следующем примере показано простое использование потоков без блокировки в 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
В следующем примере используются потоки и ключевое слово lock.Так как присутствует оператор lock, блокировка оператора является важным разделом и balance никогда не будет отрицательным числом.
// 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();
}
}
}
Спецификация языка C#
Дополнительные сведения см в Спецификация языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.
См. также
Ссылки
Ключевые слова операторов (Справочник по C#)
Синхронизация потоков (C# и Visual Basic)
Основные понятия
Руководство по программированию на C#