Неупорядоченное выполнение пары "получение-выпуск"

Я думаю о том, возможно ли для атомарной переменной загружать старое значение в пару получение-выпуск. Предположим, у нас есть атомарная переменная 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);
}

Это что-нибудь меняет?

Спасибо.

6
задан axl 15 December 2010 в 02:53
поделиться