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

时间:2016-06-13 16:47:25

标签: c# multithreading atomicity interlocked

Interlocked.Read(ref long)"是否已经过优化"在64位架构上?即如果我正在编写一个可供两种架构使用的库,我是否应该关注在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
    }

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:0)

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

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

锁定会带来相关的成本,但更高的成本来自于不编码线程安全所带来的不可预测的行为。