Ответ
Интерфейс java.util.concurrent.locks.Lock (и его реализация ReentrantLock) предоставляет более гибкий и расширенный контроль над синхронизацией по сравнению с ключевым словом synchronized.
Основные преимущества Lock:
-
Возможность попытки захвата блокировки:
Lock lock = new ReentrantLock(); if (lock.tryLock(2, TimeUnit.SECONDS)) { // Ждём не более 2 секунд try { // Критическая секция } finally { lock.unlock(); } } else { // Действие, если блокировка не получена } -
Прерываемое ожидание: Метод
lockInterruptibly()позволяет прервать поток, ожидающий блокировку. -
Честность (Fairness):
ReentrantLockможно создать с политикой честности, что уменьшает вероятность голодания потоков. -
Разделение на чтение/запись:
ReentrantReadWriteLockпозволяет множеству потоков читать данные одновременно, но блокирует их на время записи, что повышает производительность.
Стандартный шаблон использования:
Lock lock = new ReentrantLock();
// ...
lock.lock(); // Всегда перед try
try {
// Критическая секция
} finally {
lock.unlock(); // Гарантированное освобождение в finally
}
Когда использовать synchronized:
- В простых случаях, когда достаточно базовой синхронизации.
- Когда нужна встроенная поддержка мониторов (методы
wait(),notify()).
Когда использовать Lock:
- Когда нужны расширенные возможности (таймауты, прерывания, честность).
- Для реализации read-write блокировок.
- Когда логика получения/освобождения блокировки не укладывается в блоковый scope
synchronized.