Что такое потокобезопасность в Java и почему она важна?

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

Ответ

Потокобезопасность — это свойство кода, гарантирующее корректное поведение и целостность данных при одновременном выполнении в нескольких потоках.

Важность: Без потокобезопасности возникают:

  • Состояния гонки (Race Conditions): Непредсказуемый результат из-за порядка выполнения потоков.
  • Повреждение данных: Несогласованное изменение общих ресурсов.
  • Нарушение инвариантов: Объект переходит в некорректное состояние.

Пример проблемы (не потокобезопасный код):

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

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

  1. Использование потокобезопасных классов из java.util.concurrent:
    private AtomicInteger count = new AtomicInteger(0);
    public void increment() {
        count.incrementAndGet(); // Атомарная операция
    }
  2. Синхронизация доступа: Ключевое слово synchronized или объекты Lock (ReentrantLock).
  3. Иммутабельность: Использование final полей и создание неизменяемых объектов.
  4. Ограничение видимости: Использование локальных переменных или ThreadLocal.
  5. Потокобезопасные коллекции: ConcurrentHashMap, CopyOnWriteArrayList.

Важно: Избыточная синхронизация может привести к взаимным блокировкам (deadlocks) и снижению производительности.