Могут ли мониторы быть методами, а не только объектами
Что проверяют
Понимаете ли вы, к чему на самом деле привязан монитор и что захватывает synchronized-метод. Вопрос с подвохом: правильный ответ «нет», и следом обычно спрашивают, могут ли два разных synchronized-метода одного объекта выполняться одновременно.
Как отвечать
Монитор в Java всегда принадлежит объекту. У метода своего монитора нет, модификатор synchronized лишь говорит, чей монитор захватить на время вызова:
- метод экземпляра: захватывается монитор
this, это эквивалентsynchronized (this) { ... }вокруг всего тела; - статический метод: захватывается монитор объекта
Class, напримерCounter.class; - блок
synchronized (lock): монитор явно указанного объекта, чаще всего приватногоfinal Object lock.
Разница между методом и блоком видна в байткоде: у метода выставлен флаг ACC_SYNCHRONIZED, и захватом управляет JVM при вызове, а блок компилируется в инструкции monitorenter и monitorexit. Семантика одна: монитор реентерабельный, и освобождается он даже при исключении.
Отсюда практические выводы. Все synchronized-методы экземпляра одного объекта исключают друг друга, потому что делят один монитор. Статический и нестатический synchronized-методы друг друга не блокируют. wait(), notify() и notifyAll() вызываются только у объекта, чей монитор поток держит, иначе IllegalMonitorStateException.
Хорошо добавить современный контекст: в JDK 21 виртуальный поток внутри synchronized закреплялся за потоком-носителем, с JDK 24 (JEP 491) это ограничение снято. Если нужны таймауты, прерываемое ожидание или несколько условий, берут ReentrantLock и Condition.
Где спотыкаются
Отвечают «да, у каждого метода свой монитор». Тогда два синхронизированных метода одного объекта якобы работают параллельно, и на этом строится ошибочная защита данных.
Пишут поле из статического метода, а читают из метода экземпляра. Мониторы разные, взаимного исключения нет.
Синхронизируются на строковом литерале или Integer: литералы интернируются, мелкие Integer кэшируются, и посторонний код неожиданно делит с вами блокировку.