Получить доступ

Явные блокировки: ReentrantLock, RW и Condition

Когда synchronized мало, ReentrantLock с tryLock/fairness, ReadWriteLock и StampedLock, Condition вместо wait/notify.

Зачем явные Lock

synchronized прост и хорош по умолчанию, но негибок: нельзя попробовать взять замок без блокировки, прервать ожидание, задать честность или иметь несколько условий ожидания. Для этого есть java.util.concurrent.locks.Lock и его реализация ReentrantLock.

ReentrantLock даёт tryLock() (взять, если свободен), tryLock(timeout) (с таймаутом — мощное средство против deadlock), lockInterruptibly() (прерываемое ожидание), опциональную fairness (FIFO-порядок ценой пропускной способности) и несколько Condition.

Дисциплина unlock в finally

В отличие от synchronized, явный замок не освобождается автоматически. Его ОБЯЗАТЕЛЬНО снимают в finally: иначе исключение в критической секции оставит замок навсегда удержанным, и все ожидающие потоки зависнут.

lock() ставят перед try, а unlock() — в finally.

lock.lock();
try {
    updateState();
} finally {
    lock.unlock(); // всегда, даже при исключении
}

ReadWriteLock и StampedLock

ReentrantReadWriteLock разделяет доступ: много читателей одновременно ИЛИ один писатель. Выгоден для read-heavy данных, где чтения далеко преобладают; при частой записи выигрыша нет, а накладные расходы выше.

StampedLock (не реентерабельный!) добавляет оптимистичное чтение: tryOptimisticRead() возвращает «штамп», читаете данные, затем validate(stamp) проверяет, не было ли записи; если была — перечитываете под обычным read-локом. Это очень быстро для read-mostly, но требует аккуратности и не поддерживает reentrancy/Condition.

Condition

Condition — это аналог wait/notify для явных замков: lock.newCondition() даёт объект с await()/signal()/signalAll(). Главное преимущество — несколько разных условий на одном замке (например, notFull и notEmpty в ограниченной очереди), чего synchronized-монитор не умеет.

Правила те же: await() вызывают в цикле while по условию и под удерживаемым замком.

Condition notEmpty = lock.newCondition();
// потребитель:
lock.lock();
try { while (queue.isEmpty()) notEmpty.await(); take(); }
finally { lock.unlock(); }

Как отвечать на собеседовании

Назовите, что даёт ReentrantLock сверх synchronized (tryLock/timeout/interruptible/fairness/несколько Condition), подчеркните unlock в finally, объясните выигрыш ReadWriteLock на read-heavy и оптимистичное чтение StampedLock (не reentrant). Свяжите Condition с несколькими условиями на одном замке.

Вопросы по теме

Читайте также

Закрытая бета

Знать тему — половина дела

На живом собеседовании sotto слышит вопрос интервьюера и показывает короткий ответ и план. Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем