C # Блокировка объекта, который переназначается в блоке блокировки - PullRequest
4 голосов
/ 02 июня 2010

У меня есть этот код в классе:

private static MyObject _locker = new MyObject();

...

lock (_locker)
{
     ...
     _locker = new MyObject();
     ...
}

Будет ли он держать блокировку на _locker?

Ответы [ 3 ]

7 голосов
/ 02 июня 2010

Нет, не будет.Из спецификации C # (выделено моё):

Оператор блокировки вида lock (x) ..., где x - выражение ссылочного типа, точно эквивалентно

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

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

Поскольку x не переоценен, блокировка будет снята.

2 голосов
/ 02 июня 2010

Я предполагаю, что он сохранит блокировку для экземпляра MyObject, который был установлен на _locker при вызове lock, то есть он сохранит блокировку для исходного экземпляра _locker, а не для нового создан MyObject экземпляр. В следующем коде блокировка будет сохранена на MyObject("OriginalInstance") при первом вызове lock. Когда он вызывается во второй раз, он блокируется на MyObject("NewInstance").

private static MyObject _locker = new MyObject("OriginalInstance");

...

lock (_locker)
{
    ...
    _locker = new MyObject("NewInstance");
    ...
}

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

В любом случае, подобные вещи, как правило, считаются плохой практикой . См. MSDN , где приведены советы по использованию lock.

.
2 голосов
/ 02 июня 2010

Не делай этого. Попробуйте полностью использовать отдельный объект для хранения состояния блокировки, а не обязательно объект, который вы хотите защитить в операторе блокировки. Я часто пишу код (хорошо, не часто) так:

private static readonly object _locker = new object();
private static MyObject _object;
...

lock (_locker)
{
     ...
     _object = new MyObject();
     ...
}

Это включает в себя совершенно другой вид программного потока, чем тот, на который вы смотрите. lock () определяет критическую секцию в коде - вы не используете его как универсальный механизм обеспечения безопасности потоков для объектов любого типа (как я думаю, ваше намерение заключается в вашем коде?)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...