Короткий ответ
Синхронизированный нестатический метод захватывает монитор экземпляра this на всё время выполнения всего метода; статический синхронизированный метод блокирует монитор объекта класса (SomeClass.class). synchronized-блок позволяет указать, какой объект использовать как монитор, и ограничить синхронизацию только нужным фрагментом кода.
Как это работает подробнее
Пока поток внутри synchronized-метода на this, другой поток не сможет войти ни в один другой synchronized-метод того же объекта. Статические методы синхронизируются между собой на объекте Class, поэтому говорят про «класс-лок» в отличие от «объект-лока».
Блок уменьшает время удержания блокировки и снижает конкуренцию (contention), поэтому считается более гибким и, как правило, более производительным: остальной код метода выполняется без блокировки.
- Монитор в Java реентерабелен: поток, уже владеющий монитором, может повторно войти в синхронизированный код по тому же объекту без взаимной блокировки самого себя.
Пример кода
class Demo {
private final Object lock = new Object();
public synchronized void methodLockOnThis() {}
public static synchronized void staticLockOnClass() {}
public void methodWithBlock() {
synchronized (this) {} // монитор - this
synchronized (lock) {} // монитор - отдельный объект lock
// остальной код метода выполняется без блокировки
}
}Что использовать на практике
- Синхронизируй только критическую секцию через
synchronized-блок — это сокращает удержание блокировки и конкуренцию. - Для защиты всех операций над состоянием объекта используй synchronized-методы с монитором
this. - Иногда выгодно синхронизироваться на отдельном объекте-«замке», чтобы не блокировать весь экземпляр.
Подводные камни
- Нестатический и статический synchronized-методы синхронизируются на разных мониторах (
thisиClass) и не блокируют друг друга. - Синхронизация на
thisблокирует все synchronized-методы объекта, даже если нужна была лишь одна операция. - Не публикуй объект-монитор наружу: чужой synchronized по нему увеличивает время удержания и риск взаимных блокировок.
Как отвечать на собеседовании
- Сначала ответь, на каком объекте что блокируется: this для нестатического метода, Class для статического, произвольный объект для блока → покажи код → объясни выгоду блока (меньше удержание блокировки и contention) → упомяни реентерабельность монитора.