2017-02-11 6 views
3

В частности, есть ли разница между эффективным:В C++ существует ли какая-либо эффективная разница между атомарным доступом приобретения/выпуска и непринужденным доступом в сочетании с ограждением?

i = a.load(memory_order_acquire); 

или

a.store(5, memory_order_release); 

и

atomic_thread_fence(memory_order_acquire); 
i = a.load(memory_order_relaxed); 

или

a.store(5, memory_order_relaxed); 
atomic_thread_fence(memory_order_release); 

соответственно?

Неудержимые атомы доступа обеспечивают сигнальные заборы, а также заборы резьбы?

ответ

2

Вам нужно

atomic_thread_fence(memory_order_release); 
a.store(5, memory_order_relaxed); 

и

i = a.load(memory_order_relaxed); 
atomic_thread_fence(memory_order_acquire); 

Для замены

a.store(5, memory_order_release); 

и

i = a.load(memory_order_acquire); 

Непро- релаксированные атомные обращения обеспечивают сигнальные заборы, а также заборы о резьбе.

2

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

Операции по получению и освобождению от атомных переменных действуют как односторонние барьеры, но в противоположных направлениях. То есть, магазина/выпуск операции предотвращает операцию памяти, которые предшествуют его (в исходной программе) от быть заказаны после него, в то время как нагрузки/приобретает операция предотвращает операцию памяти, которые следуют его от заказано перед ним.

// thread 1 
// shared memory operations A 
a.store(5, std::memory_order_release); 

x = 42; // regular int 


// thread 2 
while (a.load(std::memory_order_acquire) != 5); 
// shared memory operations B 

операции памяти A не может двигаться вниз ниже store/release, в то время как операции с памятью В не может перемещаться вверх над load/acquire. Как только поток 2 считывает 5, операция памяти A видна для B, и синхронизация завершена.
Будучи односторонним барьером, запись в x может соединяться или даже предшествует операциям памяти A, но поскольку она не является частью отношения получения/освобождения, x не может быть надежно доступ к потоку 2.

Замена атомарных операций с автономными резьбовыми ограждениями и расслабленными операциями аналогично:

// thread 1 
// shared memory operations A 
std::atomic_thread_fence(memory_order_release); 
a.store(5, std::memory_order_relaxed); 


// thread 2 
while (a.load(std::memory_order_relaxed) != 5); 
std::atomic_thread_fence(memory_order_acquire); 
// shared memory operations B 

Это дает тот же результат, но важное различие состоит в том, что оба заборы не выступают в качестве односторонних барьеров; Если бы это произошло, атомный магазин до a мог быть переупорядочен до освобождения, а атомная нагрузка от a может быть переупорядочена после захвата забора и , что нарушит соотношение синхронизации.

В целом:

  • Автономный выпуск забор предотвращает предшествующие операции от быть заказаны с (атомными) магазинами, которые следуют за ним.
  • Автономный захват забора предотвращает переупорядочение следующих операций с (атомными) нагрузками, которые предшествуют ему.

Стандарт позволяет смешивать заготовки/выпускные ограждения с операциями Acquire/Release.

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

Это не совсем понятно мне, что вы спрашиваете здесь, потому что нить заборы, как правило, используются с расслабленными атомарных операций, но std::thread_signal_fence похож на std::atomic_thread_fence, за исключением того, что он должен работать в том же потоке и поэтому компилятор не генерирует инструкции ЦП для межпоточной синхронизации. Он в основном выступает только как компилятор.

Смежные вопросы