Почему вложенные блокировки не вызывают тупик? - PullRequest
47 голосов
/ 18 февраля 2011

Почему этот код не вызывает тупик?

   private static readonly object a = new object();

...

   lock(a)
   {
      lock(a)
      {
         ....
      }
   }

Ответы [ 3 ]

42 голосов
/ 18 февраля 2011

Если поток уже удерживает блокировку, то он может снова «взять эту блокировку» без проблем.


Что касается почему , (и почему это хорошоидея), рассмотрим следующую ситуацию, где у нас есть определенный порядок блокировки в другом месте в программе a -> b:

void f()
{
    lock(a)
    { /* do stuff inside a */ }
}

void doStuff()
{
    lock(b)
    {
        //do stuff inside b, that involves leaving b in an inconsistent state
        f();
        //do more stuff inside b so that its consistent again
    }
}

Ой, мы просто нарушили порядок блокировки и имеем потенциальный тупик в наших руках.

Мы на самом деле должны быть в состоянии сделать следующее:

function doStuff()
{
    lock(a)
    lock(b)
    {
        //do stuff inside b, that involves leaving b in an inconsistent state
        f();
        //do more stuff inside b so that its consistent again
    }
}

Так что наш порядок блокировки поддерживается, без самоблокировки при вызове f().

18 голосов
/ 18 февраля 2011

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

тупик возникает, если

Тема 1 получает блокировку A
Поток 2 приобретает блокировку B
Поток 1 пытается получить блокировку B (ожидает, когда Поток 2 завершит работу с ним) Поток 2 пытается получить блокировку A (ожидает, когда с ней завершится поток 1)

Оба потока теперь ждут друг друга и поэтому заблокированы.

8 голосов
/ 18 февраля 2011

Из раздела 8.12 спецификации языка C #:

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

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

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