2016-12-27 8 views
3

Если использовать одну атомную переменную и std::memory_order_seq_cst, неатомные операции гарантируют, что они не будут переупорядочены?Как происходит синхронизация памяти_order_seq_cst с неатомными операциями?

Например, если у меня есть

std::atomic<bool> quux = {false}; 

void foo() { 
    bar(); 
    quux.store(true, std::memory_order_seq_cst); 
    moo(); 
} 

является bar() гарантированно не получить заказана после вызова store и moo(), чтобы не заказана перед вызовом store, до тех пор, как я использую std::memory_order_seq_cst, в по крайней мере, с точки зрения другой нити?

Или, если положить его в код, допустимы следующие допущения, если они запускаются из другого потока?

if(quux.load(std::memory_order_seq_cst) == true) { 
    // bar guaranteed to be called; its side-effects are visible 
    // moo might have been called, but is not guaranteed to 
} else { 
    // bar might have been called, but is not guaranteed to 
    // moo might have been called, but is not guaranteed to 
} 

Обратите внимание, что я предполагаю, что ни bar ни moo использование атомной операции, мьютексы, замки, заборы или другие функции синхронизации.

ответ

3

Если используется одна атомная переменная и std::memory_order_seq_cst, гарантируются ли неатомные операции, которые не должны быть переупорядочены?

Стандарт довольно ясно на этом http://en.cppreference.com/w/cpp/atomic/memory_order:

memory_order_seq_cstЛюбая операция с этим порядка памяти является как операции приобретения и операции выпуска, плюс один общий порядок существует в котором все потоки все виды работ по этому заказу

memory_order_acquire Операция загрузки с этим порядком памяти выполняет операцию захвата в указанной ячейке памяти: no rea ds или записи в текущем потоке могут быть переупорядочены до этой загрузки.

memory_order_release Операция хранения с этим порядком памяти выполняет операцию освобождения: Нет чтения или записи в текущем потоке можно переупорядочить после этого магазина.

Другими словами, никакие нагрузки или магазины (как неатомные, так и атомные) могут быть переупорядочены около memory_order_seq_cst операций.


является bar() гарантированно не получить заказана после вызова магазина, и moo(), чтобы не заказан перед вызовом магазина, до тех пор, как я использую зЬй :: memory_order_seq_cst, по крайней мере, с точки зрения другой поток?

Если определения bar и moo не доступны в текущем ЕП, компилятор предполагает, что эти функции делают нагрузки памяти и/или имеют побочные эффекты (сделать I/O или сохраняет в памяти), и, следовательно, не может быть переупорядочено около memory_order_seq_cst операций.

Если определения доступны, а функции не выполняют операции ввода/вывода или памяти, они могут быть переупорядочены.Это будет pure functions или функции, которые ничего не делают и возвращают void или константу.

+0

Nitpicking, но: в то время как cppreference.com превосходный, это не стандарт ISO. – Zeta

+0

@Zeta Вы правы. Я считаю, что cppreference.com достаточно точна, но могут быть пропуски, поскольку это не копия стандарта. –

-2

Поскольку используется строжайший порядок памяти, панель функций и moo не могут быть переупорядочены мимо или до магазина до quux соответственно.

Ваш вывод для случая if-else не совсем корректен.

Если выражение if(quux.load(std::memory_order_seq_cst) == true) оценивает значение true, функциональная панель, безусловно, уже завершит свой вызов. Порядок вызова в moo не может быть определен. Возможно, оно закончилось, не началось или оно могло быть посреди вызова.

Если указанное выражение оценивается как false, мы не можем определить порядок для обеих функций. Хотя верно, что на данный момент выражение оценивается как false, функция moo еще не вызывается, ее можно вызвать сразу после этого, прежде чем выполнение перейдет к предложению else. Как только в предложении else статус функции moo будет таким же, как и в предыдущем абзаце (он не может быть определен).

0

В соответствии со ссылкой http://en.cppreference.com/w/cpp/atomic/memory_order, связанной с @Maxim, имеется ошибка в отношении memory_order_seq_cst. Текст выше обменивается с memory_order_acq_rel. Текст для memory_order_seq_cst:

memory_order_seq_cst: операция загрузки с этим порядком памяти выполняет операцию получения, хранилище выполняет операцию деблокирования, а read-modify-write выполняет как операцию получения, так и операцию освобождения плюс единую общую существует порядок, в котором все потоки соблюдают все модификации в том же порядке (см. последовательный последовательный порядок ниже)

Итак, в вашем случае операция магазина эквивалентна выпуску, что означает, что moo() можно переупорядочить перед забором.