Ответ
java.util.concurrent.locks.Lock — это интерфейс, предоставляющий расширенный механизм управления блокировками для синхронизации потоков. Основная реализация — ReentrantLock.
Ключевые преимущества перед synchronized:
| Особенность | synchronized |
Lock (например, ReentrantLock) |
|---|---|---|
| Способ управления | Неявный (ключевое слово). | Явный (вызов методов lock(), unlock()). |
| Попытка захвата с таймаутом | Нет. | Есть: tryLock(long time, TimeUnit unit). |
| Прерываемое ожидание | Нет. | Есть: lockInterruptibly(). |
| Честность (fairness) | Не гарантируется. | Можно создать честную блокировку (new ReentrantLock(true)). |
| Условные переменные | Одна (wait(), notify(), notifyAll()). |
Множественные (Condition на один Lock). |
Базовый шаблон использования Lock:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
Lock lock = new ReentrantLock();
// ...
lock.lock(); // Захват блокировки
try {
// Критическая секция — доступ к общему ресурсу
sharedResource.modify();
} finally {
lock.unlock(); // ВСЕГДА освобождайте блокировку в finally-блоке!
}
Пример с tryLock() (избегание deadlock):
if (lock1.tryLock()) {
try {
if (lock2.tryLock()) {
try {
// Работа с двумя ресурсами
} finally { lock2.unlock(); }
}
} finally { lock1.unlock(); }
}
// Если не удалось захватить обе блокировки, можно повторить попытку или выполнить альтернативную логику.
Когда использовать Lock:
- Требуется гибкость: таймауты, прерывания, чередование блокировок.
- Нужны несколько очередей ожидания (
Condition). - Логика синхронизации сложнее, чем простая блокировка метода/блока.
Когда использовать synchronized:
- Простые случаи синхронизации.
- Приоритет — читаемость и минимализм кода.
- Встроенная поддержка JVM (оптимизации, например, biased locking).