Механизм synchronized в Java основан на концепции мониторов (monitor objects). Каждому объекту в Java ассоциирован монитор.
Когда поток входит в синхронизированный блок или метод, он пытается захватить монитор соответствующего объекта. Если монитор свободен, поток захватывает его и продолжает выполнение. Если монитор занят другим потоком, текущий поток блокируется и переходит в состояние ожидания, пока монитор не освободится.
Когда поток покидает синхронизированный блок или метод (либо успешно завершив его, либо выбросив исключение), он освобождает монитор.
Внутри монитора реализованы:
wait(), notify() и notifyAll(). Эти методы позволяют потокам, владеющим монитором, временно освободить его и перейти в состояние ожидания, а затем быть уведомленными другими потоками о возможности продолжить работу.Реализация под капотом включает в себя:
monitorenter инcтрукция: Выполняется при входе в синхронизированный блок или метод. Пытается захватить монитор объекта.monitorexit инcтрукция: Выполняется при выходе из синхронизированного блока или метода (как в случае нормального завершения, так и при исключении). Освобождает монитор объекта.Эти инструкции являются частью байт-кода Java и обрабатываются виртуальной машиной Java (JVM). JVM использует нативные механизмы операционной системы (например, mutexes, semaphores) для управления мониторами и блокировкой/разблокировкой потоков.
Захват монитора может быть реализован на уровне объекта (для instance methods и blocks) или на уровне класса (для static methods и blocks), используя объект Class как блокировку.
Пример использования:
java
Таблица методов класса Object, связанных с мониторами:
| Метод | Описание |
|---|---|
wait() | Поток, владеющий монитором, временно освобождает его и переходит в ожидание. |
notify() | Уведомляет один из ожидающих потоков, что он может попытаться захватить монитор и возобновить работу. |
notifyAll() | Уведомляет все ожидающие потоки. |