Может ли поток повторно войти в synchronized метод, если он уже владеет монитором?

«Может ли поток повторно войти в synchronized метод, если он уже владеет монитором?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, может. В Java intrinsic lock (монитор) является реентерабельным (reentrant). Если поток уже владеет монитором объекта, он может повторно войти в любой synchronized метод или блок этого же объекта.

Пример реентерабельности:

public class ReentrantExample {
    public synchronized void outer() {
        System.out.println("В outer(), владею монитором.");
        inner(); // Повторный вход разрешён
    }

    public synchronized void inner() {
        System.out.println("В inner(), всё ещё владею тем же монитором.");
    }
}
// Поток, вызвавший outer(), успешно выполнит inner().

Почему это важно (reentrancy):

  1. Предотвращает самоблокировку: Поток не блокирует сам себя при вызове synchronized методов изнутри других synchronized методов того же объекта.
  2. Упрощает наследование: Если synchronized метод родительского класса вызывает переопределённый synchronized метод, поток сохраняет блокировку.
  3. Реализация: Монитор хранит счётчик вхождений и идентификатор владеющего потока. При каждом входе счётчик увеличивается, при выходе – уменьшается. Блокировка освобождается при обнулении счётчика.