← Назад к вопросам
Зачем делать переменную атомарной, если запросы в контроллер идут в одном потоке
1.7 Middle🔥 151 комментариев
#REST API и микросервисы#Многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Ответ: Атомарные переменные и многопоточность в контроллерах
Это распространённое заблуждение, что если запрос обрабатывается одним потоком, то переменные не нужно делать атомарными. На самом деле, в веб-приложениях один запрос != один поток приложения. Разберу подробно.
Основное недопонимание
Вот типичная ошибка в рассуждении:
// ❌ Неправильное понимание
public class UserCounter {
private int count = 0; // Один запрос — один поток?
@GetMapping("/increment")
public int increment() {
return ++count; // Вроде всё в одном потоке...
}
}
НО это не так! Каждый новый запрос может обрабатываться другим потоком из пула потоков servlet'а.
Как на самом деле работают контроллеры
В Spring и других веб-фреймворках используется пул потоков:
// Симуляция того, как работает веб-сервер
public class TomcatThreadPool {
private ExecutorService threadPool = Executors.newFixedThreadPool(10); // 10 потоков
// Каждый запрос обрабатывается отдельным потоком
public void handleRequest(HttpRequest request) {
threadPool.execute(() -> {
// Запрос 1 в потоке 1
// Запрос 2 в потоке 2
// Запрос 3 в потоке 3
controller.handleRequest(request);
});
}
}
Проблема с обычными переменными
// ❌ Опасный код
public class UserCounter {
private int count = 0; // Разделяется между всеми потоками!
@GetMapping("/increment")
public int increment() {
// Три потока одновременно:
// Поток 1: прочитал count=5, увеличивает
// Поток 2: прочитал count=5, увеличивает
// Поток 3: прочитал count=5, увеличивает
// Результат: count=6, хотя должен быть 8!
return ++count;
}
}
// Это называется race condition (состояние гонки)
Решение с AtomicInteger
import java.util.concurrent.atomic.AtomicInteger;
// ✅ Правильный код
public class UserCounter {
private AtomicInteger count = new AtomicInteger(0); // Потокобезопасно!
@GetMapping("/increment")
public int increment() {
// Атомарная операция: прочитать и увеличить в одном шаге
return count.incrementAndGet();
}
}
Практический пример
Атомарные переменные необходимы для потокобезопасности в многопоточной среде, которой является любое веб-приложение. Пул потоков servlet контейнера обеспечивает параллельную обработку множества запросов одновременно.