Ответ
Синхронизированный блок кода в Java блокируется по монитору объекта, указанного в операторе synchronized.
- Для синхронизированного метода используется монитор объекта, у которого вызван метод (т.е.,
thisдля нестатических методов и объект классаClassдля статических). - Для синхронизированного блока используется монитор объекта, указанного в скобках:
synchronized(object) { ... }.
Пример и объяснение:
public class Counter {
private final Object lock = new Object(); // Объект-монитор
private int count = 0;
public void increment() {
// Блокировка происходит по монитору объекта 'lock'
synchronized (lock) {
count++;
}
}
}
Почему это важно:
- Взаимоисключение: Только один поток может владеть монитором объекта в данный момент времени.
- Видимость изменений: Все изменения, сделанные в синхронизированном блоке, гарантированно становятся видимыми другому потоку после того, как он захватит тот же монитор (обеспечивает happens-before).
Лучшие практики:
- Используйте отдельный приватный объект (
private final Object lock) для блокировки вместоsynchronized(this)или синхронизированных методов, чтобы избежать непреднамеренной блокировки внешним кодом. - Следите за тем, чтобы не возник deadlock (взаимная блокировка), когда два или более потока ждут мониторы, захваченные друг другом.