Что такое ReentrantLock в Java и каковы его основные особенности?

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

Ответ

ReentrantLock — это реализация интерфейса Lock из пакета java.util.concurrent.locks, предоставляющая механизм взаимного исключения (mutex) с расширенными возможностями по сравнению с ключевым словом synchronized.

Ключевые особенности:

  • Повторная входимость (Reentrancy): Поток, уже удерживающий блокировку, может захватить её повторно без взаимной блокировки (deadlock).
  • Честность (Fairness): При создании можно указать политику честности (fair). Честная блокировка (new ReentrantLock(true)) предоставляет доступ потокам в порядке FIFO, но снижает общую пропускную способность.
  • Прерываемое ожидание: Метод lockInterruptibly() позволяет прервать поток, ожидающий блокировку.
  • Попытка захвата с таймаутом: Метод tryLock(long timeout, TimeUnit unit) пытается получить блокировку в течение заданного времени.

Пример использования:

import java.util.concurrent.locks.ReentrantLock;

ReentrantLock lock = new ReentrantLock();

lock.lock(); // Захват блокировки
try {
    // Критическая секция
    sharedResource.modify();
} finally {
    lock.unlock(); // Освобождение блокировки ВСЕГДА в finally-блоке
}
Сравнение с synchronized: Особенность synchronized ReentrantLock
Поддержка tryLock Нет Да (с таймаутом)
Честность Нет (не гарантируется) Да (опционально)
Прерываемость Нет (блокировка не прерывается) Да (lockInterruptibly)
Условные переменные Одно (wait/notify) Множество (Condition)
Синтаксис Встроенное ключевое слово Явный API, требует unlock в finally

Когда использовать? ReentrantLock выбирают, когда необходимы продвинутые функции: неблокирующие попытки захвата (tryLock), честное планирование, работа с несколькими условиями ожидания (Condition) или необходимость прерываемого ожидания блокировки.