Ответ
Монитор — это низкоуровневый, встроенный в каждый объект механизм, лежащий в основе ключевого слова 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.*.