Что указывается в скобках у оператора synchronized в Java и зачем?

«Что указывается в скобках у оператора synchronized в Java и зачем?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В скобках у оператора synchronized указывается объект-монитор (lock object), чья внутренняя блокировка (intrinsic lock) используется для синхронизации доступа к блоку кода или методу.

Зачем это нужно? Чтобы явно задать объект, на котором будет происходить синхронизация, обеспечивая тонкий контроль над параллелизмом и избегая неявных проблем.

Примеры:

public class Example {
    private final Object lock = new Object(); // Специальный объект-монитор
    private int count = 0;

    public void safeIncrement() {
        synchronized(lock) { // Синхронизация на объекте lock, а не на 'this'
            count++;
        }
    }
}

Ключевые моменты:

  • Для synchronized методов монитором неявно выступает this (для нестатических) или объект класса Class (для статических).
  • Использование отдельного приватного объекта (private final Object lock) — это best practice. Это предотвращает:
    • Внешнюю блокировку: Клиентский код не может синхронизироваться на вашем объекте, вызвав synchronized(exampleInstance), что могло бы привести к deadlock.
    • Ненужную конкуренцию: Разные блоки кода можно синхронизировать на разных объектах, увеличивая параллелизм.
  • Объект-монитор должен быть final, чтобы ссылка на него не могла измениться, иначе синхронизация будет нарушена.