Странное поведение lock () с foreach - PullRequest
4 голосов
/ 20 февраля 2009

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

У меня есть две функции в классе и блокировки

object mylock = new object();
List<string> temp = new List<string>();

Func1(string)
{
  lock(mylock)
  {
    temp.Add(string);
  }
}

Func2()
{
  lock(mylock)
  {
    temp.ForEach(p => Func1(p));
  }
}

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

Ответы [ 3 ]

13 голосов
/ 20 февраля 2009

Нет, он не должен тупиковать.

Func1 может получить блокировку, если она вызывается кем-то, кто уже удерживает блокировку (например, Func2)

Документ MSDN для блокировки объясняет:

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

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

3 голосов
/ 20 февраля 2009

Оператор lock (инкапсулирующий класс Monitor) поддерживает повторный вход (рекурсию) в потоке, т. Е. Вы можете вкладывать вызовы, которые используют один и тот же монитор.

Другие подходы к блокировке:

  • Monitor - рекурсия поддерживается
  • ReaderWriterLock - рекурсия поддерживается, но медленно
  • ReaderWriterLockSlim - рекурсия поддерживается, но не рекомендуется
  • EventHandle (ManualResetEvent, AutoResetEvent, Mutex, Semaphore) - рекурсия не поддерживается
1 голос
/ 20 февраля 2009

.NET Monitor объекты (которые использует блокировка) являются рекурсивными, поэтому поток, удерживающий блокировку, может снова свободно войти в эту блокировку.

(Не все блокирующие конструкции являются рекурсивными, и можно приводить аргументы против рекурсивной поддержки.)

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