Я думаю о том, возможно ли для атомарной переменной загружать старое значение в пару получение-выпуск. Предположим, у нас есть атомарная переменная x, и мы сохраняем эту переменную с семантикой выпуска, а затем загружаем ее с семантикой получения, возможно ли теоретически прочитать старое значение?
std::atomic<int> x = 0;
void thread_1()
{
x.store(1, std::memory_order_release);
}
void thread_2()
{
assert(x.load(std::memory_order_acquire) != 0);
}
если поток функции 1 завершен, когда поток 2 загружает x ( поэтому новое значение сохраняется) может ли поток 2 загрузить старое значение из x? Другими словами, если фактическое сохранение в x выполняется до загрузки, возможно ли срабатывание assert?
Насколько я понял из статей в Интернете, это возможно, но я не могу понять почему. Ограничение памяти, сгенерированное хранением до x, гарантирует пустой буфер хранения, в то время как ограничение памяти при загрузке из x гарантированно аннулирует строку кеша, поэтому оно должно считывать актуальное значение.
добавлено
Означает ли это что само по себе получение-выпуск не имеет принудительного упорядочивания? Это' s только все, что было сделано до выпуска, произойдет до выпуска, а все, что сделано после получения, будет происходить после него, поэтому пара получение-выпуск принудительно упорядочивает другие операции (почему?). Я правильно понял? Означает ли это, что в приведенном ниже коде assert гарантированно не запустит
std::atomic<int> x = 0;
std::atomic<int> y = 0;
void thread_1()
{
y.store(1, std::memory_order_relaxed);
x.store(1, std::memory_order_release);
}
void thread_2()
{
x.load(std::memory_order_acquire);
assert(y.load(std::memory_order_relaxed) != 0);
}
, конечно, снова, если поток 1 уже завершил сохранение. Если мы заменим x.load на while (x.load () == 0), это будет работать на 100%, но я не знаю, что заставляет это работать.
А что, если я заменю код кодом ниже
std::atomic<int> x = 0;
void thread_1()
{
x.exchange(1, std::memory_order_acq_rel);
}
void thread_2()
{
assert(x.exchange(0, std::memory_order_acq_rel) != 0);
}
Это что-нибудь меняет?
Спасибо.