Подтвердить что ты не робот

Почему Lock'ing на одном и том же объекте не вызывает блокировки?

Возможный дубликат:
Заблокированные блокировки на С#

Если я напишу какой-то код, например:

class Program {
    static void Main(string[] args) {
        Foo();
        Console.ReadLine();
    }

    static void Foo() {
        lock(_lock) {
            Console.WriteLine("Foo");
            Bar();
        }
    }

    static void Bar() {
        lock(_lock) {
            Console.WriteLine("Bar");
        }
    }

    private static readonly object _lock = new object();
}

Я получаю вывод:

Foo
Bar

Я ожидал, что это затормозит, потому что Foo приобретает блокировку, а затем ждет, когда Bar получит блокировку. Но этого не происходит.

Разрешает ли механизм блокировки это, потому что код выполняется в одном потоке?

4b9b3361

Ответ 1

Для того же потока блокировка всегда reentrant, поэтому поток может блокировать объект так часто, как он хочет.

Ответ 2

Потому что здесь есть только один поток.

lock является ярлыком для

bool lockWasTaken = false;
var temp = obj;
try { 
       Monitor.Enter(temp, ref lockWasTaken); 
       // your thread safe code
}
finally { if (lockWasTaken) Monitor.Exit(temp); }

Monitor.Enter получить монитор на объекте, переданном в качестве параметра. Если другой поток выполнил Enter на объекте, но еще не выполнил соответствующий Exit, текущий поток будет блокироваться до тех пор, пока другой поток не освободит объект. Легально, чтобы тот же поток вызывал Enter более одного раза без блокировки; однако необходимо вызывать равное количество вызовов выхода, прежде чем другие потоки, ожидающие объекта, будут разблокированы.

Ответ 3

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

Ответ 4

Одно слово: блокировка ретентата. Если поток уже приобрел блокировку, то он не ждет, хочет ли он снова получить блокировку. Это очень необходимо, иначе это могло бы превратить простые рекурсивные функции в кошмар.!