твоем примере std::exit не вызовется. seq_cst более строгая гарантия. в скомпиленном примере там вкорячем mfence, что логично. Но вот действительно ли можно seq_cst миксовать? если да, то когда и зачем? :)
btw, я открыл последний драфт и там вот (n4842, пункт 31.4 -> (4.4) ):
6 [Note: We do not require that S be consistent with “happens before” (6.9.2.1). This allows more efficient
implementation of memory_order::acquire and memory_order::release on some machine architectures.
It can produce surprising results when these are mixed with memory_order::seq_cst accesses. — end note]
7 [Note: memory_order::seq_cst ensures sequential consistency only for a program that is free of data races
and uses exclusively memory_order::seq_cst atomic operations. Any use of weaker ordering will invalidate
this guarantee unless extreme care is used. In many cases, memory_order::seq_cst atomic operations are
reorderable with respect to other atomic operations performed by the same thread. — end note]
если чо, я не настоящий сварщик и, мб, херово распарсил :)
в теории это тоже работает. Есть такая штука "CppMem: Interactive C/C++ memory model": http://svr-pes20-cppmem.cl.cam.ac.uk/cppmem/. Если загнать в неё нашу програмку которая выглядит как-то так: int main() { int v_=0; atomic_int flag_=0; {{{ { v_=1; flag_.store(1,memory_order_seq_cst); } ||| { r1=flag_.load(memory_order_acquire).readsvalue(1); r2=v_; } }}} return 0; } То можно увидеть единственное консистентное выполнение в котором нет гонок. Это даёт возможность описать "почему" в терминах "sequenced-before" и "synchronizes-with" из стандарта (https://en.cppreference.com/w/cpp/atomic/memory_order). Как-то так: В thread_write() потоке non-atomic запись значения 42 в (не-атомарную) переменную v_ "sequenced-before" sequential consistent записи 1цы в (атомарную) переменную ready_. В thread_read() acquire чтение 1цы с (атомарной) переменной ready_ "sequenced-before" non-atomic чтения из переменной v_. Так как запись 1цы в ready_ в первом потоке имеет "synchronizes-with" связь с чтением 1цы с flag-а, то из-за транзитивности имеем то что запись значения 42 в переменную v_ "synchronizes-with" чтением переменной v_. Схематично: [Thread write] Write v_ = 42 -> (sequenced-before) Write flag_ = 1 [Thread read ] Read flag_ == 1 -> (sequenced-before) Read v_ == 42 [Inter-thread] Write flag_ = 1 -> (synchronizes-with) Read Read flag_ == 1 [Conclusion ] Write v_ = 42 -> (synchronizes-with) Read v_ == 42 @antoshkka , если я правильно научился понимать cppmem, то как-то так
Обсуждают сегодня