Предположим, у меня есть тема что пишет в 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: Другими словами, делать расслабленные магазины бессмысленно
что бы то ни было, если вы не объедините их с какой-либо операцией освобождения (и
в другом потоке), если вы хотите, чтобы другой поток
видеть это?
Отметка: Почти все варианты использования для них используют освобождение и приобретение, да.
Это то, что стандарт говорит в 29.3.12:
Реализации должны сделать атомные хранилища видимыми для атомных нагрузок в течение разумного периода времени.
Там нет никакой гарантии store
станет видимым в другом потоке, нет гарантированного времени и нет формальных отношений с порядком памяти.
Конечно, на каждой обычной архитектуре store
будут становятся видимыми, но на редких платформах, которые не поддерживают когерентность кэша, они могут никогда не стать видимыми для load
,
В этом случае вам нужно будет достать атомную чтение-модификация-запись операция, чтобы получить последнее значение в порядке изменения.
Это все, что стандарт должен сказать по этому вопросу, я считаю:
[Intro.multithread] / 28 Реализация должна гарантировать, что последнее значение (в порядке модификации), назначенное атомарной операцией или операцией синхронизации, станет видимым для всех других потоков за конечный период времени.