atomic и составная операция check-then-act
Лимитер соединений написан так:
std::atomic<int> active{0};
const int kMax = 1000;
bool try_accept() {
if (active.load() < kMax) {
active.store(active.load() + 1);
return true;
}
return false;
}
В пике мониторинг показывает 1007 активных соединений при лимите 1000. Почему?
- Атомарны только отдельные `load` и `store`, а «проверить и увеличить» — составная операция: между ними вклиниваются другие потоки
- `std::atomic<int>` не атомарен на 64-битных платформах без явного указания `memory_order_seq_cst`
- Значение лимита нужно тоже сделать атомарным, иначе потоки читают устаревшую копию `kMax`
- Проблема в кэшах ядер: `load` возвращает устаревшее значение из кэша своего ядра, помогает пометить переменную ещё и `volatile`
