Каковы ключевые характеристики ключевого слова `synchronized` в Java?

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

Ответ

Ключевое слово synchronized обеспечивает синхронизацию потоков на уровне монитора объекта или класса. Его основные характеристики:

1. Взаимное исключение (Mutual Exclusion): Гарантирует, что только один поток может выполнять синхронизированный блок кода для данного монитора в один момент времени.

2. Видимость изменений (Memory Visibility): Создает отношение «происходит-до» (happens-before). Все изменения переменных, сделанные потоком перед выходом из синхронизированного блока, становятся видимыми следующему потоку, который захватит тот же монитор.

3. Повторная входимость (Reentrancy): Поток, уже владеющий монитором, может повторно войти в любой блок, синхронизированный по тому же монитору. Это предотвращает самоблокировку (self-deadlock).

4. Монитор:

  • Для нестатических методов и блоков кода монитором выступает объект (this).
  • Для статических методов и блоков synchronized(Class.class) монитором выступает объект класса (Class).

Примеры использования:

// Синхронизированный метод (монитор = this)
public synchronized void addToCounter(int value) {
    this.count += value;
}

// Синхронизированный блок с явным указанием монитора
public void updateValue(String key, Object value) {
    synchronized (this.lockObject) { // Используется отдельный объект для блокировки
        this.cache.put(key, value);
    }
}

// Синхронизированный статический метод (монитор = Class object)
public static synchronized int getGlobalCount() {
    return globalCount;
}

Недостатки и альтернативы:

  • Производительность: Избыточная синхронизация может стать узким местом.
  • Дедлоки: Неправильный порядок захвата мониторов может привести к взаимной блокировке.
  • Альтернативы: Для более гибкого управления блокировками используйте java.util.concurrent.locks.ReentrantLock. Для атомарных операций — классы из java.util.concurrent.atomic (например, AtomicInteger).