Возможно ли, что магазин с memory_order_relaxed никогда не достигнет других потоков?

Предположим, у меня есть тема что пишет в atomic_int x = 0;, с помощью x.store(1, std::memory_order_relaxed);, Без каких-либо других методов синхронизации, сколько времени потребуется, чтобы другие потоки могли это увидеть, используя x.load(std::memory_order_relaxed);? Возможно ли, что значение записано в x остается полностью ориентированным на потоки, учитывая текущее определение модели памяти C / C ++, которое дает стандарт?

Практический случай, который я имею под рукой, — это когда нить В читает atomic_bool часто проверять, должен ли он выйти; Другой поток в какой-то момент пишет правда к этому bool, а затем вызывает join () в потоке B. Очевидно, я не против вызвать join () до того, как поток B сможет даже увидеть, что был установлен atomic_bool, и не против, когда поток B уже видел изменение и вышел из выполнения до Я звоню join (). Но мне интересно: используя memory_order_relaxed с обеих сторон, возможно ли вызвать join () и заблокировать «навсегда», потому что изменение никогда не распространяется в поток B?

редактировать

Я связался с Марком Бэтти (мозгом математической проверки и последующего исправления требований к модели памяти C ++). Первоначально о чем-то другом (который оказался известной ошибкой в ​​cppmem и его тезисе; поэтому, к счастью, я не стал полностью дураком и воспользовался возможностью, чтобы спросить его об этом тоже; его ответ был:

Q: Может ли теоретически быть, что такое хранилище [memory_order_relaxed без (любой последующей) операции освобождения] никогда не достигнет другого потока?
Отметка: Теоретически да, но я не думаю, что это наблюдалось.
Q: Другими словами, делать расслабленные магазины бессмысленно
что бы то ни было, если вы не объедините их с какой-либо операцией освобождения (и
в другом потоке), если вы хотите, чтобы другой поток
видеть это?
Отметка: Почти все варианты использования для них используют освобождение и приобретение, да.

6

Решение

Это то, что стандарт говорит в 29.3.12:

Реализации должны сделать атомные хранилища видимыми для атомных нагрузок в течение разумного периода времени.

Там нет никакой гарантии store станет видимым в другом потоке, нет гарантированного времени и нет формальных отношений с порядком памяти.

Конечно, на каждой обычной архитектуре store будут становятся видимыми, но на редких платформах, которые не поддерживают когерентность кэша, они могут никогда не стать видимыми для load,
В этом случае вам нужно будет достать атомную чтение-модификация-запись операция, чтобы получить последнее значение в порядке изменения.

2

Другие решения

Это все, что стандарт должен сказать по этому вопросу, я считаю:

[Intro.multithread] / 28 Реализация должна гарантировать, что последнее значение (в порядке модификации), назначенное атомарной операцией или операцией синхронизации, станет видимым для всех других потоков за конечный период времени.

3

По вопросам рекламы [email protected]