Как работает блокировка?
Я вижу, что для использования объектов, которые не являются потокобезопасными, мы обмениваем код блокировкой следующим образом:
private static readonly Object obj = new Object();
lock (obj)
{
// thread unsafe code
}
Итак, что происходит, когда несколько потоков обращаются к одному и тому же коду (предположим, что он запущен в веб-приложении ASP.NET). Они поставлены в очередь? Если да, то как долго они будут ждать?
Какое влияние влияет на использование блокировок?
Ответы
Ответ 1
Оператор lock
переведен на С# 3.0 следующим образом:
var temp = obj;
Monitor.Enter(temp);
try
{
// body
}
finally
{
Monitor.Exit(temp);
}
В С# 4.0 это изменилось, и теперь оно создается следующим образом:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
// body
}
finally
{
if (lockWasTaken)
{
Monitor.Exit(temp);
}
}
Подробнее о том, что Monitor.Enter
делает здесь. Чтобы процитировать MSDN:
Используйте Enter
для получения объект передается как параметр. Если другой поток выполнил Enter
на объект, но еще не выполнен соответствующий Exit
, текущий поток будет блокироваться до другого поток освобождает объект. это легально для того же потока, чтобы вызвать Enter
более одного раза без него блокирование; однако, равное количество Вызов Exit
должен быть вызван до другие потоки, ожидающие объекта разблокируется.
Метод Monitor.Enter
будет бесконечно ждать; он не будет тайм-аут.
Ответ 2
Это проще, чем вы думаете.
Согласно Microsoft:
Ключевое слово lock
гарантирует, что один поток не входит в критический раздел кода, в то время как другой поток находится в критическом разделе. Если другой поток попытается ввести заблокированный код, он будет ожидать блокировки до тех пор, пока объект не будет освобожден.
Ключевое слово lock
вызывает Enter
в начале блока и Exit
в конце блока. Ключевое слово lock
фактически обрабатывает класс Monitor
на заднем конце.
Например:
private static readonly Object obj = new Object();
lock (obj)
{
// critical section
}
В приведенном выше коде сначала поток входит в критическую секцию, а затем блокирует obj
. Когда другой поток пытается войти, он также пытается заблокировать obj
, который уже заблокирован первым потоком. Второму потоку придется ждать, пока первый поток освободит obj
. Когда первый поток удаляется, другой поток блокирует obj
и входит в критическую секцию.
Ответ 3
Нет, они не поставлены в очередь, они спали
Оператор блокировки формы
lock (x) ...
где x - выражение ссылочного типа, точно эквивалентно
var temp = x;
System.Threading.Monitor.Enter(temp);
try { ... }
finally { System.Threading.Monitor.Exit(temp); }
Вам просто нужно знать, что они ждут друг друга, и только один поток войдет в блокирующий блок, остальные будут ждать...
Монитор полностью написан в .net, поэтому достаточно быстро, также посмотрите класс Monitor с reflector для более подробной информации
Ответ 4
Замки блокируют другие потоки от выполнения кода, содержащегося в блоке блокировки. Потокам придется подождать, пока поток внутри блока блокировки не завершится, и блокировка будет отпущена. Это оказывает негативное влияние на производительность в многопоточной среде. Если вам это нужно, вы должны убедиться, что код в блоке блокировки может обрабатываться очень быстро. Вы должны стараться избегать дорогостоящих действий, таких как доступ к базе данных и т.д.
Ответ 5
Влияние производительности зависит от способа блокировки. Здесь вы можете найти хороший список оптимизаций: http://www.thinkingparallel.com/2007/07/31/10-ways-to-reduce-lock-contention-in-threaded-programs/
В основном вы должны попытаться заблокировать как можно меньше, так как он заставляет ваш ожидающий код спать. Если у вас есть тяжелые вычисления или длительный код (например, загрузка файла) в блокировке, это приводит к огромной потере производительности.
Ответ 6
Часть внутри оператора блокировки может выполняться только одним потоком, поэтому все остальные потоки будут бесконечно ждать, пока поток, удерживающий блокировку, не будет завершен. Это может привести к так называемому тупику.
Ответ 7
Оператор lock
преобразуется в вызовы методов Enter
и Exit
Monitor
.
Оператор lock
будет ждать неограниченное время для освобождения объекта блокировки.
Ответ 8
замок на самом деле скрытые монитор класса.
Ответ 9
Блокировка предотвращает вход одного потока, в то время как другой уже введен. В основном это используется в многопоточности. Одним из лучших примеров, которые мы можем сказать, является шаблон проектирования "Singleton".
статический объект только для чтения obj = new object(); public static Singleton GetInstance {get {if (instance == null) {lock (obj) {if (instance == null) {instance = new Singleton(); } } } return instance; }}} return instance;
}
}