Jan*_*Jan 14 c# multithreading interlocked memory-barriers
简化问题:
与内存屏障相比,互锁操作引起的内存缓存一致性(或"刷新")的时间是否存在差异?让我们在C#中考虑 - 任何互锁操作与Thread.MemoryBarrier().我相信存在差异.
背景:
我读了很少关于内存障碍的信息 - 所有对预防特定类型的内存交互指令重新排序的影响,但是我找不到关于它们是否应该立即刷新读/写队列的一致信息.
实际上我发现很少有消息来源提到不能保证操作的即时性(只保证特定的重新排序是有保证的).例如
维基百科:"但是,要明确的是,这并不意味着任何操作都会在屏障完成时完成;只有完成操作的订购(当它们完成时)才能得到保证"
Freebsd.org(障碍是硬件特定的,所以我猜一个特定的操作系统并不重要):"内存屏障只是确定内存操作的相对顺序;它们不保证内存操作的时间"
另一方面,Interlocked操作 - 从他们的定义 - 导致立即刷新所有内存缓冲区以保证更新的最新值更新导致内存子系统用值锁定整个缓存行,以防止从任何访问(包括读取)其他CPU /核心,直到操作完成.
我纠正还是错了?
免责声明:
这是我在这里的原始问题的演变.在.NET中的可变新鲜度保证(易失性与易失性读取)
EDIT1: 修复了关于Interlocked操作的声明 - 内联文本.
编辑2: 完全删除演示代码+它的讨论(因为一些人抱怨太多的信息)
要了解C#互锁操作,您需要了解Win32互锁操作。
“纯”互锁操作本身仅影响该操作直接引用的数据的新鲜度。
但是在Win32中,互锁操作曾经暗示了完整的内存屏障。我相信这主要是为了避免在较新的硬件上破坏旧程序。因此,InterlockedAdd可以做两件事:互锁添加(非常便宜,不影响缓存)和完整的内存屏障(相当繁琐的操作)。
后来,Microsoft意识到这很昂贵,并且增加了每个操作的版本,这些版本不执行或不执行部分内存屏障。
因此,现在(在Win32世界中)几乎所有内容都有四个版本:例如InterlockedAdd(完整围栏),InterlockedAddAcquire(读取围栏),InterlockedAddRelease(写入围栏),纯InterlockedAddNoFence(无围栏)。
在C#世界中,只有一个版本,它与“经典” InterlockedAdd匹配-它也具有完整的内存范围。
简短的回答:CAS(互锁)操作已经(并且很可能会)是最快的缓存刷新器。
背景: - CAS 操作在硬件中由单个不可中断指令支持。与调用内存屏障的线程相比,内存屏障可以在放置屏障之后但在执行任何读/写之前立即进行交换(因此仍然满足屏障的一致性保证)。- CAS 操作是大多数(如果不是全部)高级同步构造(互斥体、信号量、锁 - 查看它们的实现,您会发现 CAS 操作)的基础。如果它们不能保证立即的跨线程状态一致性或者如果有其他更快的机制,则不太可能使用它们