Я думаю о том, возможно ли для атомарной переменной загрузить старое значение в паре «захват-выпуск».
Предположим, у нас есть атомарная переменная 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 сработать?
Насколько я понял из статей в интернете, это возможно, но я не могу понять, почему. Ограничение памяти, сгенерированное функцией store to x, гарантирует очистку буфера хранилища, в то время как ограничение памяти при загрузке из x гарантирует недействительность строки кэша, поэтому оно должно считывать текущее значение.
добавил
Означает ли это, что приобретение-выпуск само по себе не имеет принудительного упорядочения? Это только то, что было сделано до того, как релиз произойдет до релиза, и все, что будет сделано после получения, произойдет после него, поэтому пара переход-релиз навязывает порядок выполнения других операций (почему ??). Я правильно понял? Означает ли это, что в приведенном ниже коде 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);
}
Это что-то меняет?
Спасибо.