Ответ
Результат будет непредсказуемым и меньше ожидаемого итогового значения. Операция i++ не является атомарной. Она состоит из трех шагов: 1) чтение значения, 2) увеличение, 3) запись нового значения. Потоки могут перекрывать эти шаги, приводя к состоянию гонки (race condition) и потере обновлений.
Демонстрация проблемы:
public class UnsafeCounter {
private int count = 0;
public void increment() { count++; } // НЕБЕЗОПАСНО!
public int getCount() { return count; }
}
// Запуск двух потоков, каждый инкрементирует счетчик 100_000 раз
// Итоговое значение, скорее всего, будет меньше 200_000.
Правильные решения:
-
Использование
AtomicInteger(наиболее предпочтительно для счетчиков):private AtomicInteger atomicCount = new AtomicInteger(0); public void safeIncrement() { atomicCount.incrementAndGet(); // Атомарная операция } -
Синхронизированный метод или блок:
private int syncCount = 0; public synchronized void safeIncrement() { syncCount++; } // Или private final Object lock = new Object(); public void safeIncrement() { synchronized (lock) { syncCount++; } } -
Использование
volatileНЕ решает проблему инкремента, так как++— это операция «чтение-изменение-запись».volatileгарантирует только видимость изменений, но не атомарность составных операций.