Эффект, который вы пытаетесь создать, не зависит от неупорядоченного выполнения. Это только одна из вещей, которые могут вызвать переупорядочение памяти. Кроме того, современная x86 выполняет выполнение вне очереди, но использует буфер порядка памяти, чтобы гарантировать, что хранилища фиксируются в L1d / становятся глобально видимыми в порядке выполнения программы. (Поскольку модель памяти x86 позволяет переупорядочивать только StoreLoad, но не StoreStore.)
Переупорядочение памяти отделено от переупорядочения инструкций выполнение, потому что даже упорядоченные процессоры используют буфер хранилища, чтобы избежать остановки в хранилищах промахов кэша.
Выполнение инструкции вне очереди: сохраняется ли порядок фиксации? < / а>
Загружаются и сохраняются единственные инструкции, которые переупорядочиваются. ?
Реализация C на работающем процессоре ARM могла бы вывести 11 или 33, если x
и f
оказались в разных строках кэша.
Я предполагаю, что вы скомпилировали с отключенной оптимизацией, поэтому ваш компилятор эффективно обрабатывает все ваши переменные volatile
, т.е. volatile int x,f
. В противном случае цикл while(f==0);
будет компилироваться в if(f==0) { infloop; }
, проверяя только f
один раз. (UB гонки данных для неатомарных переменных - это то, что позволяет компиляторам выводить нагрузки из циклов, но volatile
нагрузки должны выполняться всегда. https://electronics.stackexchange.com/questions/387181/mcu-programming-c-o2-optimization-breaks- while-loop#387478 а>).
Хранилища в результирующем asm / машинном коде появятся в исходном порядке C.
Вы компилируете для x86, который имеет сильную модель памяти: хранилища x86 - это хранилища релизов, а загрузки x86 - загрузки запросов. Вы не получите последовательной согласованности, но получите acq_rel бесплатно. (А с неоптимизированным кодом это происходит, даже если вы этого не просите.)
Таким образом, при компиляции без оптимизации для x86 ваша программа эквивалентна
_Atomic int x, f;
int main(){
...
pthread_create
atomic_store_explicit(&x, 33, memory_order_release);
atomic_store_explicit(&f, 1, memory_order_release);
...
}
То же самое и со стороны нагрузки. while(f==0){}
- это загрузка-загрузка на x86, поэтому ожидание стороны чтения, пока она не увидит ненулевое значение f
, гарантирует, что она также увидит x==33
.
Но если вы скомпилировали ISA со слабым упорядочением, например ARM или PowerPC, гарантии упорядочения памяти на уровне asm позволяют переупорядочивать StoreStore и LoadLoad, так что ваша программа может печатать 11
, если скомпилирована без оптимизации.
См. Также https://preshing.com/20120930/weak-vs-strong-memory-models/
person
Peter Cordes
schedule
07.10.2018
sleep()
после его создания в основной функции, чтобы получить значение 11 - person Jean-François Fabre   schedule 07.10.2018handler
ничего не делает, покаf = 1;
не будет завершено, а к этому времениx = 33;
уже было сделано. - person Weather Vane   schedule 07.10.2018why doesn't this sometimes print "value of x is 11"?
, возможно, это и есть ответ. - person kiran Biradar   schedule 07.10.2018what
. - person kiran Biradar   schedule 07.10.2018while (f == 0);
. - person Weather Vane   schedule 07.10.201833
. Возможно, потребуется подробное объяснение того, почему последовательность выполнения потока не гарантируется. - person kiran Biradar   schedule 07.10.2018while (f == 0);
ограничения, если вы запустите программу много раз, возможно, рано или поздно планирование временного интервала отделитpthread_create(&thread1, NULL, handler, NULL);
отx = 33;
и запуститhandler
в этом крэке, чтобы сообщить11
. - person Weather Vane   schedule 07.10.2018