Ответ
Ключевое слово synchronized в Java используется для обеспечения взаимного исключения (mutual exclusion) и синхронизации потоков при доступе к общим ресурсам, предотвращая состояние гонки (race condition).
Оно может применяться двумя способами:
-
Синхронизированный блок кода:
public void increment() { synchronized (this) { // Монитором служит объект 'this' count++; // Критическая секция } }- В скобках указывается объект-монитор, блокировка которого будет захвачена перед выполнением кода в блоке.
-
Синхронизированный метод:
public synchronized void decrement() { count--; // Весь метод является критической секцией }- Для нестатического метода монитором служит объект
this(экземпляр класса). - Для статического метода монитором служит объект класса (
Classobject).
- Для нестатического метода монитором служит объект
Как это работает:
- Чтобы войти в синхронизированный блок или метод, поток должен получить блокировку (lock) на указанном объекте-мониторе.
- Если блокировка уже удерживается другим потоком, текущий поток переходит в состояние BLOCKED и ждет ее освобождения.
- Когда поток выходит из синхронизированной области (даже из-за исключения), блокировка автоматически освобождается.
Важные замечания:
synchronizedгарантирует видимость изменений (реализует happens-before), поэтому изменения, сделанные в синхронизированном блоке, становятся видимыми всем последующим потокам, которые захватят ту же блокировку.- Это реентерабельная (reentrant) блокировка: поток, уже владеющий блокировкой, может снова захватить ее (например, при рекурсивном вызове синхронизированного метода).
- Недостатки: Может приводить к взаимным блокировкам (deadlock) и снижению производительности из-за сериализации выполнения потоков. Для более сложных сценариев часто предпочтительнее использовать примитивы из пакета
java.util.concurrent.locks.