我认为在阅读网上的一些资料后,我在一定程度上了解了内存排序的各个方面。然而,仅从软件和理论的角度看这些规则似乎有点神奇。两个处理器似乎重新排序的原因的例子是explained here,并帮助我实际可视化过程。所以我所理解的是,预取器可以提前为一个处理器加载读取而不是为另一个处理器加载,然后向外部观察者看起来第一个处理器比第二个处理器更早读取(现在可能是在没有同步的情况下具有陈旧价值)并因此看到重新排序的指令。
之后我实际上是从CPU的角度寻找解释,以了解更多如何产生这样的效果。例如,考虑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;
由于在顺序属性中没有总顺序,所以thread-2可以看到thread-0做它的东西1st然后是thread-1而thread-3可以看到thread-1做它的东西1st然后是thread-0 。因此z==0
可能是一种可能的结果。
如果有一个解释(假设每个运行上面一个线程的四个cpu),硬件会发生什么事情让我们看到这个重新排序,这将是非常有帮助的。它不一定是非常复杂的真实世界详细案例(如果这是理解它的唯一方法,它可能是)。只是像上面的链接答案所做的那样近似,有关缓存(或任何参与因素)的内容,它应该为我(可能还有许多其他人?)这样做。我猜。
另一个是:
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
可能会让我们{{1} }。但是再一次看起来有点神奇,直到我能想到身体发生的方式。
因此,任何有足够数量的处理器及其缓存等帮助(或指针)的解释都是巨大的。