From Rust to reality: The hidden journey of fetch_max
В Rust есть встроенная атомарная операция fetch_max, которая отсутствует в Java и C++. Она позволяет безопасно обновлять максимальное значение в многопоточной среде без явного написания цикла CAS. Исследование показало, что fetch_max генерируется макросом atomic_int! в стандартной библиотеке Rust, который создаёт методы для атомарных типов.
На уровне компиляции LLVM эта операция превращается в цикл сравнения и обмена, скрытый от программиста. Это демонстрирует, как Rust абстрагирует сложные низкоуровневые детали, предоставляя удобные и безопасные примитивы для конкурентного программирования.
Комментарии (49)
- Автор обнаружил, что Rust имеет встроенную атомарную операцию
fetch_max, которой нет в Java и C++ (хотя она планируется в C++26). - Обсуждение затронуло технические детали реализации атомарных операций (например, на ARM и x86), их производительность при высоком уровне конкуренции и возможность компилятором оптимизировать циклы CAS в нативные инструкции.
- Участники отметили, что подобные низкоуровневые операции существуют и в других средах, таких как GPU (HLSL/GLSL/CUDA) и RISC-V.
- Многие выразили признательность автору за познавательную статью, углубившую их понимание модели памяти и атомарных операций.
- Несколько человек поинтересовались, был ли нанят кандидат, упомянутый в исходной статье, на что автор ответил, что тот не подошел по культуре.
C++: Strongly Happens Before?
Коротко о «strongly happens-before»
В C++20 появилось новое отношение strongly happens-before (SHB), потому что старое happens-before оказалось недостаточно строгим.
Пример кода
std::atomic<int> x{0}, y{0};
// thread-1
x.store(1, seq_cst);
y.store(1, release);
// thread-2
int b = y.fetch_add(1, seq_cst); // b = 1
int c = y.load(relaxed); // c = 3
// thread-3
y.store(3, seq_cst);
int a = x.load(seq_cst); // a = 0
Почему нужен SHB
- Каждый атомарный объект имеет modification order — полный порядок всех записей.
- Классические правила coherence (write-write, read-read, read-write, write-read) связывают happens-before с этим порядком.
- Но при смешанных
memory_order(например,release+seq_cst) между потоками могут образоваться «дыры», где старое happens-before не гарантирует ожидаемую последовательность.
Отличие SHB от HB
- SHB добавляет требование: если операция A strongly happens-before B, то все наблюдатели видят записи A раньше записей B, даже при разных
memory_order. - Для
seq_cstSHB совпадает с HB; дляrelease/acquireHB может быть, а SHB — нет.
Итог
Если пользуетесь только seq_cst, можно не заморачиваться. При смешанных порядках SHB — формальный способ не получить «невозможные» значения.
Комментарии (14)
- Участники обсуждают различие между «strong happens-before» в Java и более слабой моделью C++.
- Код из статьи считается не «простым», а академическим примером; порядок запуска потоков ОС не гарантирует.
- Наблюдаемые в комментариях значения могут показаться странными, но они допустимы при отсутствии дополнительной синхронизации.
- Смысл слабых моделей памяти — формально описать множество всех допустимых исполнений, учитывая кэши, оптимизации компилятора и т. д.
- Добавление ещё одного атомика для «упорядочивания» может, наоборот, запретить именно тот «неинтуитивный» порядок, который автор статьи исследует.