Чем монитор отличается от других примитивов синхронизации в Java?

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

Ответ

Монитор — это низкоуровневый, встроенный в каждый объект механизм, лежащий в основе ключевого слова synchronized. Другие примитивы синхронизации (из java.util.concurrent) — это высокоуровневые, более гибкие и производительные абстракции.

Сравнительная таблица:

Примитив Ключевая особенность Когда использовать
Монитор (synchronized) Встроен в язык, прост в использовании. Одна блокировка на объект (вход/выход). Простые случаи, когда достаточно базовой блокировки. Легаси-код.
ReentrantLock Явная блокировка. Расширенные возможности: tryLock(), честность, несколько Condition. Когда нужны возможности, отсутствующие у synchronized.
Semaphore Управляет доступом к пулу ресурсов (N разрешений). Не является блокировкой владения. Ограничение количества одновременных потоков, например, к соединению с БД.
CountDownLatch Ожидание завершения набора операций в других потоках. Счетчик уменьшается, но не сбрасывается. Запуск потоков одновременно или ожидание инициализации сервисов.
CyclicBarrier Ожидание, пока N потоков не достигнут барьера, затем все продолжают. Сбрасывается и используется повторно. Многоэтапные параллельные вычисления (например, итеративные алгоритмы).

Пример, где ReentrantLock предпочтительнее монитора:

import java.util.concurrent.locks.ReentrantLock;

public class InterruptibleLocking {
    private final ReentrantLock lock = new ReentrantLock();

    public void performTask() throws InterruptedException {
        // Пытаемся захватить блокировку с возможностью прерывания ожидания
        if (lock.tryLock(1, TimeUnit.SECONDS)) {
            try {
                // Критическая секция
                System.out.println("Lock acquired by " + Thread.currentThread().getName());
            } finally {
                lock.unlock(); // Всегда освобождаем в finally
            }
        } else {
            System.out.println("Could not acquire lock");
        }
    }
}

Вывод: Монитор (synchronized) — это основа, но для сложных сценариев конкурентности следует использовать более специализированные классы из java.util.concurrent.*.