Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Java: synchronized, reentrant, Java, thread safety, lock

Является ли synchronized reentrant?

Этот вопрос проверяет понимание механизма повторного входа (reentrancy) в synchronized-методах и блоках Java, что важно для предотвращения взаимоблокировок (deadlocks) при рекурсивных вызовах.

Короткий ответ

Да, synchronized в Java является реентерабельным (reentrant). Это означает, что поток, уже владеющий монитором объекта, может снова войти в synchronized-блок или метод, защищённый тем же монитором, без блокировки самого себя. Это предотвращает взаимоблокировки в рекурсивных вызовах или когда один synchronized-метод вызывает другой synchronized-метод того же объекта. Без этой возможности поток заблокировал бы сам себя, что привело бы к deadlock.

Длинный ответ

В Java ключевое слово synchronized используется для обеспечения синхронизации потоков, гарантируя, что только один поток может выполнять определённый блок кода или метод объекта в данный момент времени. Это достигается путём захвата монитора (внутренней блокировки), связанного с объектом.

Что такое реентерабельность (Reentrancy)?

Реентерабельная блокировка (reentrant lock) — это блокировка, которая позволяет потоку, уже владеющему ею, снова её захватить. Это критически важно для ситуаций, где синхронизированный код может вызывать сам себя, например, при рекурсии или когда один синхронизированный метод вызывает другой синхронизированный метод того же объекта.

Как работает реентерабельность synchronized?

Каждый объект в Java имеет связанный с ним счётчик вхождений (entry count) для монитора. Когда поток впервые входит в synchronized-блок для объекта, счётчик устанавливается в 1, и поток становится владельцем монитора. Если тот же поток снова входит в synchronized-блок для того же объекта, счётчик увеличивается. При выходе из блока счётчик уменьшается, и когда он достигает нуля, монитор освобождается, позволяя другим потокам захватить его.

Пример кода

public class ReentrantExample {
    public synchronized void outerMethod() {
        System.out.println("Внешний метод, владею монитором.");
        innerMethod(); // Рекурсивный вызов другого synchronized-метода
    }

    public synchronized void innerMethod() {
        System.out.println("Внутренний метод, тот же поток входит снова.");
    }

    public static void main(String[] args) {
        ReentrantExample obj = new ReentrantExample();
        // Один поток вызовет оба метода
        new Thread(() -> obj.outerMethod()).start();
    }
}

В этом примере поток, вызвав outerMethod(), захватывает монитор объекта obj. При вызове innerMethod() из outerMethod() тот же поток успешно входит, потому что synchronized реентерабелен. Без реентерабельности это привело бы к deadlock.

Где это применяется?

  • Рекурсивные алгоритмы: Синхронизированные рекурсивные методы работают корректно.
  • Цепочки вызовов: Когда один синхронизированный сервисный метод вызывает другой в том же объекте.
  • Наследование: Если synchronized-метод переопределяется в подклассе и вызывает super.method().

Вывод: Реентерабельность synchronized в Java — это важное свойство, которое предотвращает самоблокировку потоков и упрощает разработку многопоточных приложений, особенно при использовании рекурсии или сложных цепочек вызовов внутри одного объекта. Это делает synchronized более безопасным и удобным для базовых сценариев синхронизации.

Уровень

  • Рейтинг:

    3

  • Сложность:

    5

Навыки

  • Java

    Java

Ключевые слова

#synchronized

#reentrant

#Java

#thread safety

#lock

Подпишись на Java Developer в телеграм