Может ли правило согласованности чтения-четения выводить порядок модификации в зависимости от значения чтения?

Вопрос или проблема

[intro.races] стр. 16 говорит:

Если вычисление значения A атомного объекта M происходит до вычисления значения B для M, и A получает свое значение из побочного эффекта X на M, то значение, вычисленное B, является либо значением, сохраненным X, либо значением, сохраненным побочным эффектом Y на M, где Y следует за X в порядке модификации M.

Это правило обычно можно интерпретировать, используя следующий пример:

std::atomic<int> x{0};
// поток 1:
x.store(1); // #1
x.store(2); // #2

// поток 2:
x.load(); // #3
x.load(); // #4

Согласно [intro.races] стр. 15, #2 следует за #1 в порядке модификации x, и если #3 читает 1, то #4 может быть 1 или 2 в соответствии с [intro.races] стр. 16. В этом случае выделенный “где” пункт накладывает требование: если B не читает X, то он должен читать какой-то побочный эффект, который следует за X в порядке модификации.

Тем не менее, рассмотрим следующий пример:

std::atomic<int> x{0};
// поток 1:
x.store(3);  // #1
// поток 2:
x.store(4);  // #2
// поток 3:
x.load();  // #3
x.load();  // #4

Если #3 прочитал 3, а #4 прочитал 4, можем ли мы заключить, что 4 следует за 3 в порядке модификации согласно [intro.races] стр. 16? Насколько я понимаю, текущее wording (т.е. “где” пункт) не означает, что он задает порядок для Y, другими словами, он не говорит ничего вроде: если B читает Y, то Y следует за X в порядке модификации.

Мне интересно, можно ли использовать правило согласованности чтения для вывода порядка модификации во втором примере.

Ответ или решение

По вопросу о том, может ли правило согласованности чтения-чтения (read-read coherence rule) выводить порядок модификаций на основе читаемого значения, можно сказать следующее.

Начнем с того, что правило согласованности чтения, описанное в [intro.races], гласит, что если вычисление значения A атомарного объекта M предшествует вычислению значения B объекта M, и A получает значение от побочного эффекта X на M, то значение, вычисляемое B, будет либо значением, записанным X, либо значением, записанным побочным эффектом Y на M, где Y следует за X в порядке модификаций M.

Рассмотрим первый пример, который вы привели:

std::atomic<int> x{0};
// поток 1:
x.store(1); // #1
x.store(2); // #2

// поток 2:
x.load(); // #3
x.load(); // #4

В этом случае говорит о том, что #2 действительно следует за #1 в порядке модификаций объекта x. Если #3 читает значение 1, то #4 может читать либо 1, либо 2. И действительно, в соответствии с акцентированной частью правила, если B (в данном случае #4) не считывает значение, записанное X (то есть значение 1), оно должно считывать какое-либо значение, которым является побочный эффект Y, следующее за X в порядке модификаций.

Теперь перейдем ко второму примеру:

std::atomic<int> x{0};
// поток 1:
x.store(3);  // #1
// поток 2:
x.store(4);  // #2
// поток 3:
x.load();  // #3
x.load();  // #4

Здесь мы имеем два потоковых действия (потоки 1 и 2), оба записи в атомарный объект. Если #3 читает значение 3 и #4 читает значение 4, мы сталкиваемся с вопросом о порядке модификаций. В данном случае, согласно определению, изменение значения 4 в потоке 2 не связано с чтением значения 3 в потоке 3 напрямую через согласованность чтения.

Правило, сформулированное в [intro.races], не предоставляет нам возможность однозначно утверждать, что 4 следует за 3 в порядке модификаций только на основании того, что #3 прочитал 3, а #4 прочитал 4. Чтобы утверждать, что #4 (считывающее значение 4) следует за #3 (считывающим значение 3) в порядке модификаций, необходимо больше информации о том, что произошло между этими нагруженными потоками.

Итак, в данном контексте нельзя сделать вывод о том, что модификации следуют друг за другом просто на основании значений, считанных различными потоками. Порядок истинных модификаций требует явного контроля над доступом к атомарным объектам и, соответственно, задачи анализа должны учитывать не только значения, но и видимые зависимости, возникающие в результате межпотокового взаимодействия.

Таким образом, правило согласованности чтения не может использоваться для вывода порядка модификаций в приведенном вами втором примере, так как оно не однозначно указывает на вопрос, каким образом отдых влияния на порядок чтения значений потоков может быть объединен с побочными эффектами в условиях конкурирующих записей.

Оцените материал
Добавить комментарий

Капча загружается...