Что такое синхронизация на объекте класса (Class object) в Java и когда она применяется?

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

Ответ

Синхронизация на объекте класса (Class<?>) — это механизм обеспечения потокобезопасности для статических методов и статических данных. В отличие от синхронизации на экземпляре (this), которая защищает нестатические члены, блокировка на Class объекте является общей для всех экземпляров класса.

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

public class SharedStaticResource {
    private static int counter = 0;

    // Способ 1: synchronized в объявлении статического метода
    public static synchronized void increment() {
        counter++;
    }

    // Способ 2: synchronized блок на Class объекте (эквивалентен способу 1)
    public static void decrement() {
        synchronized (SharedStaticResource.class) {
            counter--;
        }
    }

    // Нестатический метод — синхронизируется на экземпляре (this)
    public synchronized void instanceMethod() {
        // Защищает нестатические поля
    }
}

Когда применять синхронизацию на Class объекте:

  1. Защита статических переменных: Когда несколько потоков изменяют общие статические данные.
  2. Потокобезопасность статических методов: Если статический метод работает с общими ресурсами.
  3. Синхронизация доступа к ресурсам уровня класса: Например, к статическому кэшу или подключению к базе данных.

Важные замечания:

  • Блокировка на Class объекте не защищает нестатические поля.
  • Все synchronized static методы класса используют одну и ту же блокировку (Class объект), что может привести к конкуренции.
  • Для более тонкого контроля можно использовать отдельные static final объекты-замки:

    public class FineGrainedLock {
    private static final Object staticLock = new Object();
    private static int value = 0;
    
    public static void safeOperation() {
        synchronized (staticLock) { // Блокировка на отдельном объекте
            value++;
        }
    }
    }

Вывод: Синхронизация на Class объекте — инструмент для защиты статических данных, но требует осторожности из-за потенциальных узких мест.