Что такое монитор в Java и как он работает?
Что проверяют
Знаете ли вы, что стоит за словом synchronized, и понимаете ли, что монитор даёт не только взаимное исключение, но и видимость изменений между потоками. Вопрос базовый, поэтому ценится точность, а не длина.
Как отвечать
Монитор это связанная с объектом пара: блокировка и набор ожидания. Поток входит в синхронизированный блок, захватывает монитор объекта, на выходе освобождает, в том числе при исключении. В байт-коде это monitorenter и monitorexit, у синхронизированного метода флаг ACC_SYNCHRONIZED.
Что стоит назвать:
- монитор даёт видимость: освобождение блокировки происходит до её захвата следующим потоком, поэтому изменения полей видны без
volatile; - блокировка реентерабельная, владелец спокойно входит во вложенную секцию;
- метод экземпляра берёт монитор
this, статический метод берёт монитор объекта класса, и это разные блокировки; wait()освобождает монитор и уводит поток в набор ожидания,notify()возвращает его в очередь на захват, аsleep()монитор не отдаёт;wait()вызывается только внутри цикла с проверкой условия, из-за ложных пробуждений и чужих уведомлений.
Полезно уточнить, что отдельная структура монитора не создаётся на каждый объект заранее: состояние блокировки лежит в заголовке объекта, тяжёлый вариант появляется при конкуренции.
ReentrantLock берут, когда нужны попытка захвата с таймаутом, прерываемое ожидание, несколько условий или честная очередь.
Где спотыкаются
Синхронизируют разные объекты и считают, что защитили общее состояние. Два экземпляра это два монитора, а статический и обычный синхронизированные методы одного класса друг друга не исключают вообще.
Ставят wait() под if вместо while и получают поток, проснувшийся при невыполненном условии. Рядом та же ошибка с выбором объекта блокировки: синхронизация на строковом литерале или на боксированном числе захватывает то, что разделяется всей программой через пул.
Называют взаимную блокировку, но не могут сформулировать правило профилактики: единый порядок захвата и никаких сетевых вызовов внутри критической секции. Долгая операция под блокировкой убивает пропускную способность надёжнее, чем сама конкуренция.