В чем разница между загрузкой/сохранением расслабленной атомарной и обычной переменной?
Меня глубоко впечатлил этот ответ:
Использование атомарной переменной решает проблему: все
потоки гарантированно прочитают последнее записанное значение, даже если
порядок памяти ослаблен.
Сегодня я прочитал ссылку ниже:
https://preshing.com/20140709/the-membe ... -in-cpp11/
Код: Выделить всё
atomic Guard(nullptr);
int Payload = 0;
Код: Выделить всё
Payload = 42;
Guard.store(&Payload, memory_order_release);
Код: Выделить всё
g = Guard.load(memory_order_consume);
if (g != nullptr)
p = *g;

ВОПРОС:
Я узнал, что Зависимость данных предотвращает переупорядочение связанных инструкций.
Но я думаю, что это очевидно для обеспечения правильности результатов выполнения. Не имеет значения, существует ли семантика comsume-release или нет.
Так что мне интересно, действительно ли comsume-release существует. О, может быть, он использует зависимости данных, чтобы предотвратить изменение порядка инструкций, гарантируя видимость полезной нагрузки?
Так
Это можно получить тот же правильный результат, используя Memory_order_relaxed, если я сделаю эту 1.предотвращение переупорядочения инструкций
2.обеспечение видимости неатомарной переменной полезной нагрузки
:
Код: Выделить всё
atomic Guard(nullptr);
volatile int Payload = 0; // 1.Payload is volatile now
// 2.Payload.assign and Guard.store in order for data dependency
Payload = 42;
Guard.store(&Payload, memory_order_release);
// 3.data Dependency make w/r of g/p in order
g = Guard.load(memory_order_relaxed);
if (g != nullptr)
p = *g; // 4. For 1,2,3 there are no reorder, and here, volatile Payload make the value of 42 is visable.
1.Payload = 42;
Летучий make запись полезных данных в/из основной памяти, но не в/из кэша. Таким образом, 42 будет записывать в память.
2.Guard.store(&Payload, любой флаг MO можно использовать для письмо); Как вы сказали, Guard является энергонезависимым, но атомарным.
Использование атомарной переменной решает проблему - при использовании атомарности все
потоки гарантированно будут читайте последнее записанное значение, даже если
порядок памяти ослаблен.
Фактически, атомарность всегда потокобезопасна, независимо от
порядка памяти! Порядок памяти не для атомарных -> он предназначен для неатомарных
данных.
Поэтому после выполнения Guard.store, Guard.load ( с любым флагом MO, который можно использовать для чтения), можно правильно получить адрес полезной нагрузки. А затем правильно получите 42 из памяти.
Приведенный выше код:
1. Нет эффекта переупорядочения для зависимости данных.
2.нет эффекта кэширования для энергозависимой полезной нагрузки
3.нет проблем с потокобезопасностью для атомной защиты
Могу ли я получить правильное значение - 42?
Вернуться на главную вопрос
Когда вы используете семантику потребления, вы по сути пытаетесь заставить
компилятор использовать зависимости данных на всех этих семействах процессоров .
Поэтому, как правило, недостаточно просто заменить
memory_order_acquire на Memory_order_consume. Вы также должны убедиться, что
на уровне исходного кода C++ существуют цепочки зависимостей данных.

" Вы также должны убедиться, что на уровне исходного кода C++ существуют цепочки зависимостей данных. ."
Я думаю, что цепочки зависимостей данных на уровне исходного кода C++ препятствуют естественному переупорядочению инструкций.
Итак, что на самом деле делает Memory_order_consume?
И могу ли я использовать Memory_order_relaxed для достижения того же результата, что и приведенный выше код?
Конец дополнительного контента
Подробнее здесь: https://stackoverflow.com/questions/653 ... -really-do
Мобильная версия