У меня есть вопрос относительно порядка операций в следующем коде:
std::atomic<int> x;
std::atomic<int> y;
int r1;
int r2;
void thread1() {
y.exchange(1, std::memory_order_acq_rel);
r1 = x.load(std::memory_order_relaxed);
}
void thread2() {
x.exchange(1, std::memory_order_acq_rel);
r2 = y.load(std::memory_order_relaxed);
}
Учитывая описание std::memory_order_acquire
на странице cppreference (https://en.cppreference.com/w/cpp/atomic/memory_order), это
Операция загрузки с этим порядком памяти выполняет операцию получения в затронутой ячейке памяти: никакие чтения или записи в текущем потоке не могут быть переупорядочены до этой загрузки.
кажется очевидным, что никогда не может быть результата, что r1 == 0 && r2 == 0
после одновременного запуска thread1
и thread2
.
Тем не менее, я не могу найти какой-либо формулировки в стандарте C++ (глядя на проект C++ 14 прямо сейчас), который устанавливает гарантии того, что две ослабленные нагрузки не могут быть переупорядочены с обменом приобретением-выпуском. Что мне не хватает?
EDIT: Как было предложено в комментариях, на самом деле можно получить равные нулю значения r1 и r2. Я обновил программу, чтобы использовать load-приобретать следующим образом:
std::atomic<int> x;
std::atomic<int> y;
int r1;
int r2;
void thread1() {
y.exchange(1, std::memory_order_acq_rel);
r1 = x.load(std::memory_order_acquire);
}
void thread2() {
x.exchange(1, std::memory_order_acq_rel);
r2 = y.load(std::memory_order_acquire);
}
Теперь можно получить оба и r1
и r2
равным 0 после одновременного выполнения thread1
и thread2
? Если нет, какие C++ правила предотвращают это?