Я думаю, что я понимаю аспекты порядка упорядочения памяти в некоторой степени после прочтения нескольких материалов в сети. Однако, кажется немного волшебным смотреть на правила только с программной и теоретической точки зрения. Примером того, почему два процессора могут показаться переупорядоченными, является объяснил здесь и очень помог мне реально визуализировать процесс. Так что я понял, что средство предварительной выборки может загрузить чтение для одного процессора раньше, а для другого — нет, тогда для внешнего наблюдателя это будет выглядеть так, как если бы 1-й процессор читал раньше, чем 2-й (и потенциально мог теперь имеют устаревшее значение в отсутствие синхронизации) и, таким образом, видят переупорядоченные инструкции.
После этого я действительно искал объяснения с точки зрения процессора, чтобы узнать, как можно получить такие эффекты. Например, рассмотрим acquire-release
забор. Классический пример этого обычно цитируется примерно так:
thread-0: x.store(true,std::memory_order_release);
thread-1: y.store(true,std::memory_order_release);
thread-2:
while(!x.load(std::memory_order_acquire));
if(y.load(std::memory_order_acquire)) ++z;
thread-3:
while(!y.load(std::memory_order_acquire));
if(x.load(std::memory_order_acquire)) ++z;
Так как не существует полного порядка, как в последовательной согласованности, поток-2 может видеть, как поток-0 выполняет свою работу 1-й, а затем поток-1, а поток-3 может видеть, как поток-1 выполняет свою работу 1-й, а затем — поток 0 таким образом z==0
может быть возможным результатом.
Если бы было объяснение (скажем, взятие четырех процессоров, каждый из которых запускает один из потоков выше) и то, что произойдет с аппаратным обеспечением, чтобы мы увидели этот порядок, это было бы чрезвычайно полезно. Это не должен быть очень сложный подробный случай из реального мира (может быть, если это единственный способ понять это). Просто приближение, подобное тому, что делает приведенный выше ответ, с добавлением чего-то о кеше (или любом участвующем факторе), это должно сделать это для меня (и, вероятно, многих других?), Я думаю.
Еще один:
thread-0:
x.store(true,std::memory_order_relaxed);
y.store(true,std::memory_order_release);
thread-1:
while(!y.load(std::memory_order_acquire)); // <------ (1)
if(x.load(std::memory_order_relaxed)) ++z;
Следуя правилам снова, я могу понять, что это никогда не получится z==0
(при условии, что все начальные значения равны 0) и почему меняется (1)
в relaxed
может получить нас z==0
, Но еще раз это кажется волшебным, пока я не могу думать о том, как это может физически бывает.
Таким образом, любая помощь (или указатели), требующие достаточного количества процессоров, их кеша и т. Д. Для объяснения, была бы огромной.
Задача ещё не решена.
Других решений пока нет …