Существует ли способ обнаружить, если объект заблокирован?

Я всегда использую отдельную переменную для соединений:

object syncObj = new object();

void Foo()
{
  lock(syncObj)
  {
    // do some stuff
  }
}

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

Для некоторой информации о том, как Монитор был первоначально предназначен, чтобы использоваться, см. Монитор (синхронизация)

46
задан ChrisWue 20 October 2013 в 20:14
поделиться

4 ответа

Вы всегда можете вызвать статический метод TryEnter в классе Monitor , используя значение 0 в качестве значения для ожидания . Если он заблокирован, вызов вернет false.

Однако проблема здесь в том, что вам нужно убедиться, что список, к которому вы пытаетесь синхронизировать доступ, заблокирован сам по себе, чтобы синхронизировать доступ.

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

Помните, что блокировка может быть на любом другом, поэтому просто вызовите это в этом списке бессмысленно, если вы не уверены, что именно этот список заблокирован.

43
ответ дан 26 November 2019 в 20:33
поделиться

Monitor.TryEnter завершится успешно, если объект не заблокирован, и вернет false, если в этот самый момент объект заблокирован. Однако обратите внимание, что здесь есть неявная гонка: экземпляр, возвращаемый этим методом, объект больше не может быть заблокирован.

11
ответ дан 26 November 2019 в 20:33
поделиться

В настоящее время вы можете вызвать Monitor.TryEnter, чтобы проверить, заблокирован ли объект или нет.

В .NET 4.0 команда CLR собирается добавить «API проверки блокировки»

Вот цитата из статьи Рика Байерса :

проверка блокировок
Мы добавляем несколько простых API-интерфейсов в ICorDebug, которые позволяют вам исследовать управляемые блокировки (мониторы). Например, если поток заблокирован в ожидании блокировки, вы можете узнать, какой другой поток в настоящее время удерживает блокировку (и если есть тайм-аут).

Таким образом, с помощью этого API вы сможете проверить:
1) Какой объект удерживает замок?
2) Кто его ждет?

Надеюсь, это поможет.

6
ответ дан 26 November 2019 в 20:33
поделиться

Я не уверен, что статический вызов TryEnter с временем 0 гарантирует, что блокировка не будет получена, если она доступна. Решение, которое я сделал для проверки в режиме отладки, что переменная sync заблокирована, было следующим:

#if DEBUG
// Make sure we're inside a lock of the SyncRoot by trying to lock it.
// If we're able to lock it, that means that it wasn't locked in the first
// place.  Afterwards, we release the lock if we had obtained it.
bool acquired = false;
try
{
    acquired = Monitor.TryEnter(SyncRoot);
}
finally
{
    if (acquired)
    {
        Monitor.Exit(SyncRoot);
    }
}
Debug.Assert(acquired == false, "The SyncRoot is not locked.");
#endif
7
ответ дан 26 November 2019 в 20:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: