Threading.Volatile.Read(Int64)和Threading.Interlocked.Read(Int64)之间的区别?

Mar*_* Ba 6 c# multithreading volatile interlocked

Read(Int64).NET系统类System.Threading.Volatile和的方法有什么区别System.Threading.Interlocked

具体而言,关于(a)原子性和(b)内存排序,它们各自的保证/行为是什么。

请注意,这是关于Volatile阶级,不是volatile(小写)的关键字。


MS docs状态:

易读方法

读取字段的值。在需要它的系统上,插入一个内存屏障,以防止处理器按以下方式重新排序内存操作:如果在代码中此方法之后出现读取或写入,则处理器无法在此方法之前移动它。

...

退货 Int64

读取的值。不管处理器数量或处理器缓存状态如何,此值都是计算机中任何处理器最新写入的值。

Interlocked.Read(Int64)方法

返回作为原子操作加载的64位值。

似乎特别令人困惑的是,这些Volatile文档没有谈论原子性,并且这些Interlocked文档没有谈论排序/内存障碍。

旁注:作为参考:我更熟悉C ++原子API,其中原子操作也总是指定内存排序语义。


Pavel有用地提供的问题链接(和可传递链接)很好地解释了挥发性记忆屏障和原子无撕裂阅读的区别/正交性,但它们并没有解释这两个概念如何应用于这两个类别。

  • 是否Volatile.Read保证原子性?
  • 是否Interlocked.Read(或者,真的,任何的Interlocked功能)做出的内存为了任何保证?

Kev*_*sse 6

Interlocked.Read translates into a CompareExchange operation:

public static long Read(ref long location)
{
    return Interlocked.CompareExchange(ref location, 0, 0);
}
Run Code Online (Sandbox Code Playgroud)

Therefore it has all the benefits of CompareExchange:

  • Full memory barrier
  • Atomicity

Volatile.Read on the other hand has only acquire semantics. It helps you ensuring the execution order of your read operations, without any atomicity or freshness guarantee.

  • @MartinBa我假设两者都是以相同的方式实现的(使用“lock cmpxchg”指令),所以比较它们是公平的。在描述内存模型时,.net 文档非常糟糕(有时甚至是错误的)。 (2认同)
  • 据我了解,这是因为 32 位和 64 位架构上的“Int32”原子性得到保证,而不需要“Interlocked”。因此,您只需要使用“Volatile.Read(ref int arg)”即可获得相同的保证。我相信在 64 位架构上,`Interlocked.Read()` 相当于 `Volatile.Read()`,因为原子性已经得到保证。 (2认同)