Ответ 1
Если поток уже содержит блокировку, то он может "принять эту блокировку" снова без проблем.
Что касается того, почему это (и почему это хорошая идея), рассмотрим следующую ситуацию, когда у нас есть определенный порядок блокировки в другом месте программы 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()
.