Является ли Scope Singleton в Spring потокобезопасным по умолчанию?

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

Ответ

Нет, по умолчанию Singleton-бин в Spring не является автоматически потокобезопасным. Его потокобезопасность зависит от наличия и управления изменяемым состоянием (mutable state).

  • Stateless-бины (без состояния) безопасны: Если бин только содержит логику или финальные/неизменяемые данные, он безопасен для использования из множества потоков.
  • Stateful-бины (с состоянием) требуют защиты: Если бин имеет изменяемые поля, разработчик должен самостоятельно обеспечить синхронизацию доступа.

Пример потоконебезопасного Singleton-бина:

@Service // По умолчанию Scope = Singleton
public class UnsafeCounterService {
    private int count = 0; // Изменяемое состояние, общее для всех потоков

    public void increment() {
        count++; // Неатомарная операция (чтение-изменение-запись)
    }
}

Способы обеспечения потокобезопасности:

  1. Использование атомарных классов из java.util.concurrent.atomic:

    @Service
    public class SafeCounterService {
        private final AtomicInteger count = new AtomicInteger(0);
    
        public void increment() {
            count.incrementAndGet(); // Атомарная и потокобезопасная операция
        }
    }
  2. Синхронизация (менее предпочтительно из-за производительности):
    public synchronized void increment() {
        count++;
    }
  3. Использование потокобезопасных коллекций (например, ConcurrentHashMap).

Вывод: Spring управляет жизненным циклом одного экземпляра Singleton-бина, но не гарантирует его потокобезопасность. Ответственность лежит на разработчике.