Interlocked.Read/Exchange for longs on 64-bit architectures

Interlocked.Read/Exchange for longs on 64-bit architectures

Interlocked.Read(ref long) "optimized away" 是在 64 位架构上吗? IE。如果我正在编写一个可以被两种架构使用的库,我是否应该担心在 64 位 CPU 上不必要地使用 Interlocked.Read 对性能的影响?

我想过使用这样的东西,所以我想知道这是否有意义:

    // X64 is a preprocessor constant set for x64 builds  

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static long Read(ref long address)
    {
#if X64
        // atomic on 64-bit processors
        return address;
#else
        // if I got it right, this creates a full memory barrier
        return Interlocked.Read(ref address);
#endif
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void Write(ref long address, long value)
    {
#if X64
        // atomic on 64-bit processors
        address = value;
#else
        // if I got it right, this creates a full memory barrier
        Interlocked.Exchange(ref address, value);
#endif
    }

我只能回答第二个问题——你不应该关心它。您所能做的就是确定对变量的读写是否需要线程安全并相应地编写代码。 C# 是一种抽象——你是为语言而不是处理器编写的。编译器和 .NET 框架担心处理器。

64 位读取保证在 64 位处理器上是原子的,但正如您所说,您正在为两种体系结构编写。如果锁定成本是您可以在 64 位架构上避免的重大障碍,那么该障碍在 32 位架构上将是一个未解决的问题。

锁定会产生一定的成本,但更大的成本来自于未针对线程安全进行编码而导致的不可预测的行为。

是的,您不必要地担心 Interlocked 的性能影响,因为 Interlocked 只是 对值执行原子操作,它还确保该值对所有线程可见(顺序一致性)。让我解释。 在某些架构(包括某些 64 位架构)上,写入内存位置的值可能会被缓存以提高性能。尽管是原子操作,但简单地读取一个值可能不会读取另一个线程写入的 "latest" 值。 Interlocked 还执行内存栅栏,以便栅栏之前的任何操作都将缓存的值刷新到实际内存中。 因此,虽然您可能会稍微提高性能,但您也会引入潜在的竞争条件。在这不是问题的架构上,Interlocked 不会执行额外的工作并为您进行优化。

不幸的是,Interlocked 的文档仍然 没有完全符合这些细节。有关 Interlocked 操作中涉及的围栏的更多详细信息,请参阅 http://www.albahari.com/threading/part4.aspx