内存屏障vs内存对内存的影响缓存一致性时序

简化问题:

与内存屏障相比,由互锁操作引起的内存缓存一致性(或“刷新”)的时间是否存在差异? 让我们在C#中考虑 – 任何互锁操作与Thread.MemoryBarrier()。 我相信存在差异。

背景:

我读了很少关于内存障碍的信息 – 所有对预防特定类型的内存交互指令重新排序的影响,但是我找不到关于它们是否应该立即刷新读/写队列的一致信息。

我实际上发现很少有消息来源提到不保证操作的即时性(只保证特定的重新排序是有保证的)。 例如

维基百科 :“但是,要明确的是,这并不意味着任何操作都会在屏障完成时完成;只有完成操作的订购(当它们完成时)才能得到保证”

Freebsd.org (障碍是硬件特定的,所以我猜一个特定的操作系统并不重要):“内存屏障只是确定内存操作的相对顺序;它们不保证内存操作的时间”

另一方面,Interlocked操作 – 从他们的定义 – 导致立即刷新所有内存缓冲区以保证更新的最新值更新导致内存子系统用值锁定整个缓存行,以防止从任何访问(包括读取)其他CPU /核心,直到操作完成。

我纠正还是错了?

免责声明:

这是我在这里的原始问题的演变。 在.NET中的可变新鲜度保证(易失性与易失性读取)

EDIT1:修复了关于Interlocked操作的声明 – 内联文本。

编辑2:完全删除演示代码+它的讨论(因为一些人抱怨太多的信息)

要了解C#互锁操作,您需要了解Win32互锁操作。

“纯”互锁操作本身仅影响操作直接引用的数据的新鲜度。

但在Win32中,互锁操作过去常常意味着完全的内存屏障。 我相信这主要是为了避免在新硬件上破坏旧程序。 所以InterlockedAdd做了两件事:互锁添加(非常便宜,不影响缓存)和完全内存屏障(相当重的操作)。

后来,微软意识到这是昂贵的,并且每个操作的增加版本没有或部分内存屏障。

所以现在(在Win32世界中)几乎所有东西都有四个版本:例如InterlockedAdd(全栅栏),InterlockedAddAcquire(读栅栏),InterlockedAddRelease(写栅栏),纯InterlockedAddNoFence(无栅栏)。

在C#world中,只有一个版本,它与“经典”InterlockedAdd相匹配 – 它也可以完整的内存栅栏。

简短回答:CAS(Interlocked)操作已经(并且很可能将)成为最快的缓存。

背景: – 通过单个不可中断指令在HW中支持CAS操作。 与线程调用内存屏障相比,线程调用内存屏障可以在放置屏障后立即交换,但在执行任何读/写之前(因此仍然满足屏障的一致性)。 – CAS操作是大多数(如果不是全部)高级同步构造的基础(互斥体,sempahores,锁 – 查看它们的实现,你会发现CAS操作)。 如果它们不能保证立即跨线程状态一致性或者是否存在其他更快的机制,则不可能使用它们

至少在英特尔设备上,一堆机器码操作可以以LOCK前缀为前缀,这确保将以下操作视为primefaces操作,即使基础数据类型不能一次性适合数据总线,例如,LOCK REPNE SCASB将扫描一串字节以获得终止零,并且不会被其他线程中断。 据我所知,Memory Barrier构造基本上是一个基于CAS的自旋锁,它使一个线程等待满足某些条件,例如没有其他线程有任何工作要做。 这显然是一个更高级别的构造,但不要错误,那里有一个条件检查,它可能是primefaces的,也可能是CAS保护的,当你到达时你还是要支付缓存行价格记忆障碍。