Монитор против замка
когда уместно использовать либо Monitor
или lock
ключевое слово для потокобезопасности в C#?
EDIT:
Кажется из ответов так далеко, что lock
короткая рука для серии звонков в Monitor
класса. Для чего именно нужен короткий вызов замка? Или более явно,
class LockVsMonitor
{
private readonly object LockObject = new object();
public void DoThreadSafeSomethingWithLock(Action action)
{
lock (LockObject)
{
action.Invoke();
}
}
public void DoThreadSafeSomethingWithMonitor(Action action)
{
// What goes here ?
}
}
обновление
спасибо всем за помощь : я отправил еще один вопрос в продолжение некоторых информацию вы все предоставили. Поскольку вы, кажется, хорошо разбираетесь в этой области, я разместил ссылку:что не так с этим решением для блокировки и управления заблокированными исключениями?
7 ответов:
Эрик Липперт говорит об этом в своем блоге: блокировки и исключения не смешиваются
эквивалентный код отличается между C# 4.0 и более ранних версий.
в C# 4.0 это:
bool lockWasTaken = false; var temp = obj; try { Monitor.Enter(temp, ref lockWasTaken); { body } } finally { if (lockWasTaken) Monitor.Exit(temp); }
он полагается на
Monitor.Enter
атомарная установка флага при снятии блокировки.
а раньше было:
var temp = obj; Monitor.Enter(temp); try { body } finally { Monitor.Exit(temp); }
Это зависит от того, что между
Monitor.Enter
иtry
. Я думаю, что в отладке код это условие было нарушено, потому что компилятор вставил NOP между ними и, таким образом, сделал прерывание потока между ними возможным.
lock
- Это просто ярлык дляMonitor.Enter
Сtry
+finally
иMonitor.Exit
. Используйте оператор блокировки всякий раз, когда этого достаточно - если вам нужно что-то вроде TryEnter, вам придется использовать монитор.
оператор блокировки эквивалентен:
Monitor.Enter(object); try { // Your code here... } finally { Monitor.Exit(object); }
однако имейте в виду, что монитор также может ждать() и Pulse (), которые часто полезны в сложных многопоточных ситуациях.
обновление
однако в C# 4 его реализовали по-другому:
bool lockWasTaken = false; var temp = obj; try { Monitor.Enter(temp, ref lockWasTaken); //your code } finally { if (lockWasTaken) Monitor.Exit(temp); }
Thanx в CodeInChaos для комментариев и ссылки
как говорили другие,
lock
"эквивалентно"Monitor.Enter(object); try { // Your code here... } finally { Monitor.Exit(object); }
но просто из любопытства,
lock
сохранит первую ссылку, которую вы передаете ему, и не будет бросать, если вы ее измените. Я знаю, что не рекомендуется менять заблокированный объект и вы не хотите этого делать.но, опять же, для науки, это прекрасно работает:
var lockObject = ""; var tasks = new List<Task>(); for (var i = 0; i < 10; i++) tasks.Add(Task.Run(() => { Thread.Sleep(250); lock (lockObject) { lockObject += "x"; } })); Task.WaitAll(tasks.ToArray());
...И это не значит:
var lockObject = ""; var tasks = new List<Task>(); for (var i = 0; i < 10; i++) tasks.Add(Task.Run(() => { Thread.Sleep(250); Monitor.Enter(lockObject); try { lockObject += "x"; } finally { Monitor.Exit(lockObject); } })); Task.WaitAll(tasks.ToArray());
ошибка:
исключение типа 'System.Нарезка резьбы.SynchronizationLockException' произошло в 70783студии.exe, но не был обработан в пользовательском коде
дополнительная информация: метод синхронизации объектов был вызван из несинхронизированный блок кода.
это так
Monitor.Exit(lockObject);
будет действовать наlockObject
, который был изменен, потому чтоstrings
являются неизменяемыми, то вы вызываете его из несинхронизированного блока кода.. но все равно. Это просто забавный факт.
Это одно и то же. блокировка-это ключевое слово C sharp и класс монитора использования.
http://msdn.microsoft.com/en-us/library/ms173179 (v = vs. 80). aspx
блокировка и основное поведение монитора (ввод + выход) более или менее одинаковы, но монитор имеет больше опций, что позволяет вам больше возможностей синхронизации.
блокировка-это ярлык, и это вариант для основного использования.
Если вам нужно больше контроля, монитор является лучшим вариантом. Вы можете использовать Wait, TryEnter и Pulse для расширенных применений (таких как барьеры, семафоры и т. д.).