Основное различие между простыми / обычными блокировками и повторными входящими блокировками состоит в том, что простые блокировки позволяют одному потоку получать блокировку в данный момент времени, заставляя каждый другой поток ожидать, включая поток, который удерживает блокировку, если он попытался заблокировать снова. Повторно входящие блокировки позволяют одному и тому же потоку захватывать блокировку столько раз, сколько необходимо, при условии, что они уже удерживают блокировку и сохраняют все другие потоки в очереди ожидания для той же блокировки.
Блокировка повторного входа обычно полезна, когда необходима рекурсия. Представьте, что у вас есть рекурсивная функция, которая должна получить блокировку для выполнения. Если вы использовали простую блокировку, ваш первый поток может легко заблокировать сам себя. Первая итерация рекурсии успешно получит блокировку, вторая итерация попытается снова получить блокировку, но заблокирует навсегда. Вторая итерация будет ожидать разблокировки первой итерации, но первая итерация не будет разблокирована, пока вторая итерация не завершится.
Повторная входная блокировка полезна здесь, потому что, как только поток удерживает блокировку, он может блокировать столько раз, сколько пожелает после этого. Единственный улов в том, что вашему потоку придется разблокировать столько раз, сколько он заблокировал, что делает его похожим на счетный семафор.