Что происходит, когда 3 «хранилища» происходят последовательно и только один атомный - PullRequest
2 голосов
/ 15 марта 2020

Я попытался свести это к простому примеру для ясности. У меня есть своего рода флаг atomi c, который используется для указания того, что одна вещь только что завершена, а другая еще не запущена. Обе эти вещи включают хранение данных в буфере. Я пытаюсь выяснить, как работает ржавчина Упорядочение релизов специально, чтобы понять, как это сделать. Рассмотрим «очень упрощенный» пример:

use std::sync::atomic::{AtomicU32,Ordering};

fn main(){
    let mut a = 0;
    let mut b = AtomicU32::new(0);
    let mut c = 0;

    // stuff happens

    a = 10;
    b.store(11,Ordering::Release);
    c = 11;
}

В частности, необходимо поддерживать инвариант типа, который атомиум c сохраняет в переменной b, происходит после a и до c, но ни один из эти переменные или операции их хранения могут быть атомами c в действительности (да, в примере они могут быть, но это для упрощения / визуализации). Я хотел бы избежать мьютекса, если смогу (не хочу отвлекать внимание от вопроса, почему).

Когда я читаю порядок Release , это сильно указывает на то, что присвоение переменной "a" должно произойти до сохранения в b:

В сочетании с хранилищем все предыдущие операции становятся упорядоченными до любой загрузки этого значения с упорядочением Приобретения (или более сильным). В частности, все предыдущие записи становятся видимыми для всех потоков, которые выполняют загрузку (или более сильную) этого значения. Обратите внимание, что использование этого заказа для операции, которая объединяет нагрузки и накопления, приводит к операции расслабленной загрузки! Этот порядок применим только для операций, которые может выполнить магазин. Соответствует memory_order_release в C ++ 20.

Однако это не гарантирует, что присвоение переменной c не может быть перемещено до сохранения в переменной b. Почти все, что я читаю, всегда говорит о том, что сохранение / загрузка до операции atomi c гарантированно произойдет раньше, но не дает никаких гарантий относительно перемещения операций в другом направлении через границу.

Правильно ли я беспокоюсь, что присвоение переменной c может быть перемещено перед сохранением в b, если используется порядок выпуска?

Я рассматривал другие вопросы, такие как Какие std :: syn c :: atomi c :: Порядок использования? и другие подобные вопросы о переполнении стека, но они не охватывают вопрос о том, можно или нет переместить c до b, используя release как я вижу.

1 Ответ

0 голосов
/ 20 марта 2020

В ответ на мой собственный вопрос: Да, я должен быть обеспокоен тем, что присвоение C может быть переупорядочено до B, поскольку порядок «Release» только предотвращает перемещение A мимо B. Путем установки забора с упорядочением Release между назначения B и C, я также могу предотвратить переупорядочение C до B (так как это предотвратит B после C, что тоже самое).

Все это относится к Хранение CPU / порядок загрузки. То, будет ли хранилище atomi c и ограждение мешать компилятору также перемещать эти операции, зависит от компилятора, и к его документации следует обращаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...