Что такое состояние гонки (race condition) при инкрементации переменной в Java?

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

Ответ

Состояние гонки возникает, когда несколько потоков одновременно выполняют неатомарную операцию инкремента (count++), что может привести к потере обновлений.

Почему это происходит? Операция count++ состоит из трёх шагов:

  1. Чтение текущего значения из памяти
  2. Увеличение значения на 1
  3. Запись нового значения обратно в память

Если два потока выполняют эти шаги параллельно, они могут прочитать одинаковое значение, увеличить его и записать, перезаписав изменения друг друга.

Пример проблемы:

public class RaceConditionExample {
    private int counter = 0;

    public void unsafeIncrement() {
        counter++;  // Непотокобезопасно!
    }
}

Решения:

  1. Использование AtomicInteger (рекомендуется):
    
    private AtomicInteger safeCounter = new AtomicInteger(0);

public void safeIncrement() { safeCounter.incrementAndGet(); // Атомарная операция }


2. **Синхронизация:**
```java
public synchronized void safeIncrement() {
    counter++;
}
  1. Использование volatile (не решает проблему инкремента, только видимость):
    private volatile int counter = 0;
    // Требует дополнительной синхронизации для инкремента