Чем отличаются memory_order_seq_cst и memory_order_acq_rel?

В вашем вопросе вы спросили о регулярном выражении, и я большой поклонник и пользователь из них, поэтому, когда мне нужно было сделать такой же аргумент, как и вы, я написал свое собственное регулярное выражение после того, как искал его и не нашел простого решения , Мне нравятся короткие решения, поэтому я сделал один, и вот он:

            var re = @"\G(""((""""|[^""])+)""|(\S+)) *";
            var ms = Regex.Matches(CmdLine, re);
            var list = ms.Cast<Match>()
                         .Select(m => Regex.Replace(
                             m.Groups[2].Success
                                 ? m.Groups[2].Value
                                 : m.Groups[4].Value, @"""""", @"""")).ToArray();

Он обрабатывает пробелы и кавычки внутри кавычек и преобразует закрытые «" в ". Не стесняйтесь использовать код!

24
задан R. Martinho Fernandes 9 September 2012 в 16:27
поделиться

3 ответа

http://en.cppreference.com/w/cpp/atomic/memory_order имеет хороший пример внизу , который работает только с memory_order_seq_cst. По существу, memory_order_acq_rel обеспечивает порядок чтения и записи относительно атомарной переменной, в то время как memory_order_seq_cst обеспечивает порядок чтения и записи глобально. То есть последовательно согласованные операции видны во всех потоках в одном и том же порядке.

Пример сводится к следующему:

bool x= false;
bool y= false;
int z= 0;

a() { x= true; }
b() { y= true; }
c() { while (!x); if (y) z++; }
d() { while (!y); if (x) z++; }

// kick off a, b, c, d, join all threads
assert(z!=0);

Операции над z защищены двумя атомными переменными, а не одной, поэтому вы не можете использовать семантику acqu-release для принудительного выполнения этого z всегда увеличивается.

26
ответ дан Drew Dormann 9 September 2012 в 16:27
поделиться

По-прежнему использовать определение и пример из memory_order . Но замените memory_order_seq_cst на memory_order_release в магазине и memory_order_acquire при загрузке.

Упорядочение Release-Acquire гарантирует все, что происходило до того, как хранилище в одном потоке становится видимым побочным эффектом в потоке, который выполнил загрузку. Но в нашем примере ничего не происходит до того, как сохранит как в thread0, так и в thread1.

x.store(true, std::memory_order_release); // thread0

y.store(true, std::memory_order_release); // thread1

Более того, без memory_order_seq_cst последовательное упорядочение thread2 и thread3 не гарантируется. Вы можете представить, что они становятся:

if (y.load(std::memory_order_acquire)) { ++z; } // thread2, load y first
while (!x.load(std::memory_order_acquire)); // and then, load x

if (x.load(std::memory_order_acquire)) { ++z; } // thread3, load x first
while (!y.load(std::memory_order_acquire)); // and then, load y

Итак, если thread2 и thread3 выполняются до thread0 и thread1, это означает, что x и y остаются ложными, таким образом, ++ z никогда не затрагивается, z остается 0 и Утверждает огонь.

Однако, если memory_order_seq_cst входит в изображение, он устанавливает единый общий порядок изменения всех атомарных операций, которые так помечены. Таким образом, в thread2 x.load затем y.load; в thread3, y.load, а затем x.load - это точно.

1
ответ дан jun.wu 9 September 2012 в 16:27
поделиться

На ISAs как x86, где карта атомной энергетики к барьерам и фактическая модель машины включают буфер хранилища:

  • seq_cst хранилища требуют сбрасывания буфера хранилища, таким образом, более поздние чтения этого потока задержаны, пока хранилище не глобально видимо.
  • acq_rel делает не , сбрасывают буфер хранилища. Нормальные загрузки x86 и хранилища имеют по существу acq и семантика рэла. (seq_cst плюс хранилище буферизуют с передачей хранилища.)

    , Но x86 атомарные операции RMW всегда продвигаются на seq_cst, потому что префикс x86 asm lock является полным барьером памяти. Другой ISAs может сделать ослабленный или acq_rel RMWs в asm.

https://preshing.com/20120515/memory-reordering-caught-in-the-act является поучительным примером различия между хранилищем seq_cst и простым хранилищем выпуска. (Это на самом деле mov + mfence по сравнению с плоскостью mov в x86 asm. На практике xchg более эффективный способ сделать хранилище seq_cst на большинстве x86 центральных процессоров, но GCC действительно использует mov + mfence)

Забавный факт: инструкция хранилища выпуска AARCH64 STLR на самом деле последовательна - выпуск. В аппаратных средствах это имеет загрузки/хранилища с расслабленным или seq_cst и барьерами для получения других преимуществ. Но к сожалению я думаю, рэл или acq_rel должны быть усилены к seq_cst, потому что нет никакого барьера или инструкции, которая дает все rel потребности, не будучи еще более сильной и более дорогой. Некоторые другие ISAs (как PowerPC) имеют больше вариантов барьеров и могут усилиться [до 1 111] или mo_acq_rel более дешево, чем [1 113].

2
ответ дан 28 November 2019 в 00:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: