← Назад к вопросам

Для чего нужен AtomicInteger?

2.0 Middle🔥 201 комментариев
#JVM и память#Многопоточность и асинхронность

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Назначение AtomicInteger

AtomicInteger — это класс из пакета java.util.concurrent.atomic, который предоставляет атомарные операции над целочисленным значением. Его основное предназначение — обеспечение потокобезопасности при работе с целочисленными переменными в многопоточных средах без использования явных блокировок (synchronized).

Проблема, которую решает AtomicInteger

В многопоточном приложении обычные операции инкремента (i++) или декремента не являются атомарными. Они выполняются в три этапа:

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

Если два потока одновременно выполняют инкремент, может произойти состояние гонки (race condition), и итоговое значение будет некорректным.

// Потокобезопасная проблема с обычным int
private int counter = 0;
// counter++ в многопоточном окружении может привести к потере обновлений

Ключевые преимущества AtomicInteger

  • Атомарность операций: Все методы класса (например, incrementAndGet(), getAndAdd()) выполняются как единая неделимая операция.
  • Высокая производительность: Использует аппаратную поддержку атомарных операций (через CAS — Compare-And-Swap) вместо тяжеловесных блокировок.
  • Отсутствие блокировок (non-blocking): Потоки не приостанавливаются, а повторяют операцию в случае конфликта, что повышает эффективность при высокой конкуренции.

Основные методы AtomicInteger

import java.util.concurrent.atomic.AtomicInteger;

public class Counter {
    private AtomicInteger atomicCounter = new AtomicInteger(0);
    
    // Атомарно увеличивает на 1 и возвращает новое значение
    public int increment() {
        return atomicCounter.incrementAndGet();
    }
    
    // Атомарно добавляет указанное значение
    public int add(int delta) {
        return atomicCounter.addAndGet(delta);
    }
    
    // Атомарно устанавливает значение, если текущее равно ожидаемому (CAS-операция)
    public boolean compareAndSet(int expect, int update) {
        return atomicCounter.compareAndSet(expect, update);
    }
    
    // Получение текущего значения
    public int get() {
        return atomicCounter.get();
    }
}

Принцип работы CAS (Compare-And-Swap)

В основе AtomicInteger лежит алгоритм CAS:

  1. Сохраняется текущее значение переменной.
  2. Вычисляется новое значение.
  3. Запись происходит только если текущее значение все еще равно сохраненному (значит, его не изменил другой поток).
  4. Если значение изменилось, операция повторяется.
// Приблизительная реализация CAS-логики
public boolean weakCompareAndSet(int expect, int update) {
    // На уровне процессора выполняется атомарная инструкция
    // CMPXCHG на x86 или аналогичная на других архитектурах
}

Типичные сценарии использования в Android

  • Счетчики в многопоточных операциях (например, счетчик загруженных файлов).
  • Генератор уникальных ID в фоновых задачах.
  • Флаги и состояния общие для нескольких потоков.
  • Итераторы в параллельных коллекциях.
// Пример в Kotlin
val requestIdGenerator = AtomicInteger(0)

fun generateRequestId(): Int {
    return requestIdGenerator.incrementAndGet()
}

// Использование в многопоточном окружении
class ImageLoader {
    private val activeDownloads = AtomicInteger(0)
    
    fun trackDownloadStart() {
        activeDownloads.incrementAndGet()
        updateUI()
    }
    
    fun trackDownloadFinish() {
        activeDownloads.decrementAndGet()
        updateUI()
    }
}

Сравнение с альтернативами

ПодходПотокобезопасностьПроизводительностьСложность
Обычный intНетВысокаяНизкая
synchronizedДаНизкая (блокировки)Средняя
AtomicIntegerДаВысокая (беспробудные)Низкая

Ограничения и предосторожности

  • Составные операции все еще требуют синхронизации (например, проверка-затем-действие).
  • Проблема ABA: Значение может измениться с A на B и обратно на A, что CAS посчитает корректным (для сложных случаев используйте AtomicStampedReference).
  • Не подходит для сложных объектов — только для целочисленных значений.

AtomicInteger является оптимальным выбором для простых атомарных операций с целыми числами в многопоточных Android-приложениях, обеспечивая баланс между безопасностью и производительностью.

Для чего нужен AtomicInteger? | PrepBro