Скажем, в моем коде есть следующие глобальные переменные:
std::atomic<uint32_t> x(...);
std::atomic<uint32_t> y(...);
std::atomic<uint32_t> z(...);
Моя задача - умножить x и y, а затем сохранить результат в z:
z = x * y
Я знаю, что наивный подход вызова store () и load () для каждого объекта совершенно неверен:
z.store(x.load() * y.load()); // wrong
Таким образом, я выполняю три отдельные атомарные инструкции: другой поток может проскользнуть и изменить одно из значений за это время.
Я мог бы выбрать цикл сравнения и замены (CAS), но он гарантировал бы атомарность только для замены старого значения z
на новое (x*y
): я все еще не уверен, как выполнить всю операцию за один атомный шаг.
Мне также известно, что обертывание x
, y
и z
внутри структуры и сделать его атомарным здесь неосуществимо, поскольку структура не помещается в один 64-битный регистр. Компилятор будет использовать блокировки под капотом (поправьте меня, если я здесь не прав).
Эта проблема разрешима только с мьютексом?