Монитор в Java
У каждого Java-объекта есть связанный с ним intrinsic monitor. Концептуально он объединяет:
- блокировку с единственным владельцем;
- счетчик реентерабельных входов;
- набор потоков, ожидающих через
wait().
Это не список «всех синхронизаторов»: Semaphore, CountDownLatch и ReentrantLock — отдельные механизмы.
private final Object monitor = new Object();
private boolean ready;
void awaitReady() throws InterruptedException {
synchronized (monitor) {
while (!ready) {
monitor.wait();
}
}
}
void markReady() {
synchronized (monitor) {
ready = true;
monitor.notifyAll();
}
}synchronized (monitor) захватывает монитор. wait() временно освобождает именно его. notifyAll() переводит ожидающих в борьбу за повторный захват; вызывающий поток продолжает владеть монитором до выхода из блока.
Какой объект является монитором
- у
synchronizedinstance-метода —this; - у
static synchronized—CurrentClass.class; - у блока — выражение в
synchronized (expression).
Синхронизация работает только при совпадении объекта по идентичности. Два равных через equals() объекта — два разных монитора.
Не стоит использовать публичные строки, boxed numbers или this библиотеки как lock: внешний код способен захватить тот же объект. Предпочтителен private final Object lock = new Object().
На собеседовании
- Монитор и mutex — одно и то же? Monitor включает mutual exclusion и механизм ожидания условия; mutex описывает только взаимное исключение.
- Освобождает ли
notifyAll()monitor? Нет, только выход из synchronized. - Совпадают ли мониторы равных объектов? Нет, важна идентичность.
- Где ждут потоки
wait()? В wait set конкретного объекта.