2013-02-22 2 views
3

В Monitor документации .NET Framework 4.5 я нашел предложение, в котором говорится, что блокировка ключевых слов использует Enter(Object, Boolean) метод Monitor:Заблокировать вызовы ключевых слов Monitor.Enter (Object) или Enter (Object, Boolean)?

Функциональные возможности, предоставляемые Ввод и методы выхода идентичны, обеспечиваемый C# замок (SyncLock в Visual Basic), за исключением того, что lock и SyncLock переносят перегрузку метода Enter (Object, Boolean) и метод Exit в try ... finally block (Попробуйте ... Наконец, на Visual Basic), чтобы убедиться, что монитор выпущен.

С другой стороны, в overwiew из Monitors есть:

Визуальное заявления # блокировки Основные SyncLock и C использовать MonitorEnter взять замок и MonitorExit, чтобы освободить его.

MonitorEnter в выше, относится к другой версии Enter метода, чем предыдущий, а именно: Enter(Object)

В Thread Synchronization (C# and Visual Basic) для Visual Studio 2012 есть пример, как замок обручи Монитор:

System.Object obj = (System.Object)x; 
System.Threading.Monitor.Enter(obj); 
try 
{ 
    DoSomething(); 
} 
finally 
{ 
    System.Threading.Monitor.Exit(obj); 
} 

Eсть тоже Enter(Object) версия.

Что такое истина? Записывает ли запрос блокировки Enter(Object, Boolean) или Enter(Object)? Есть ли какая-то разница, как это делается?

+0

Они оба верны. Зависит от той версии .NET, на которую вы нацеливаетесь. –

+0

@HansPassant: Я получаю эти кавычки только из .NET 4.5 и Visual Studio 2012. –

ответ

5

От Eric Lippert’s Blog:

Напомним, что lock(obj){body} был [в C# 3.0 и выше] синтаксический сахар для

var temp = obj; 
Monitor.Enter(temp); 
try { body } 
finally { Monitor.Exit(temp); } 

Проблема здесь в том, что если компилятор генерирует команду не-оп между монитор входит в зону защиты, защищенную от попыток, тогда во время выполнения можно запустить исключение прерывания потока после входа монитора, но перед попыткой. В этом случае, наконец, никогда не запускается, поэтому утечка блокировки, возможно, в конечном итоге затормозит программу. Было бы неплохо, если бы это было невозможно в неоптимизированных и оптимизированных сборках.

В C# 4.0 мы изменили замок, так что теперь генерирует код, как если бы это были

bool lockWasTaken = false; 
var temp = obj; 
try { Monitor.Enter(temp, ref lockWasTaken); { body } } 
finally { if (lockWasTaken) Monitor.Exit(temp); } 

Проблема теперь становится чужой проблемой; реализация Monitor.Enter берет на себя ответственность за атомарную установку флага таким образом, который невосприимчив к исключениям прерывания потока, которые испортили его.

Итак, все хорошо сейчас, правда?

К сожалению, нет.[...]

С другой стороны, C# 4.0 Language Specification говорит:

Заявление замок формы

lock (x) ... 

, где х представляет собой выражение опорного типа, в точности эквивалентно

System.Threading.Monitor.Enter(x); 
try { 
    ... 
} 
finally { 
    System.Threading.Monitor.Exit(x); 
} 

за исключением того, что x является только e оценивается один раз.

+0

Документация относится к 4.5 и Visual Studio 2012. Они просто копируют устаревший старый текст? –

+0

Возможно, Microsoft реализует Enter (Object, Boolean) и тем самым разбивает половину своей документации и стандарта. Другие, вероятно, реализуют стандарт. –

+0

Поскольку Эрик Липперт был [частью команды дизайна C#] (http://ericlippert.com/2012/11/29/fabulous-adventures/), есть хороший шанс, что он знает, о чем он говорит, и что он прав чем документация. – Virtlink

Смежные вопросы