C# Interlocated.Read/Exchange用于64位体系结构上的long
C# Interlocated.Read/Exchange用于64位体系结构上的long,c#,multithreading,atomicity,interlocked,C#,Multithreading,Atomicity,Interlocked,是互锁的。读取(参考长度)在64位体系结构上“优化”了吗?也就是说,如果我正在编写一个可供两种体系结构使用的库,我是否应该担心在64位CPU上不必要地使用互锁读取对性能的影响 我考虑过使用类似的东西,所以我想知道这是否有意义: // X64 is a preprocessor constant set for x64 builds [MethodImpl(MethodImplOptions.AggressiveInlining)] public static lon
是互锁的。读取(参考长度)
在64位体系结构上“优化”了吗?也就是说,如果我正在编写一个可供两种体系结构使用的库,我是否应该担心在64位CPU上不必要地使用互锁读取对性能的影响
我考虑过使用类似的东西,所以我想知道这是否有意义:
// 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 framework担心处理器
64位读取保证在64位处理器上是原子的,但正如您所说,您正在为这两种体系结构编写。如果锁定成本是一个在64位体系结构上可以避免的重大障碍,那么该障碍在32位体系结构上将是一个未解决的问题
锁定会带来成本,但更大的成本将来自不为线程安全编码的不可预测行为。是的,您不必要地担心联锁的性能影响,因为联锁的
不仅仅对值执行原子操作,它还确保该值对所有线程可见(顺序一致性)。让我解释一下。
在某些体系结构(包括某些64位体系结构)上,写入内存位置的值可以缓存以提高性能。尽管是原子操作,但仅仅读取一个值可能不会读取另一个线程写入的“最新”值<代码>联锁
还执行内存隔离,以便隔离之前的任何操作都会将任何缓存值刷新到实际内存中。
因此,虽然您可能会稍微提高性能,但您也引入了潜在的竞争条件。在不存在此问题的体系结构上,Interlocked
将不会执行额外的工作,而是为您进行优化
遗憾的是,<代码>联锁的文档在这些细节上仍然不太符合标准。有关联锁
操作中涉及的围栏的更多详细信息,请参阅。您不必担心“使用联锁对性能的影响。阅读
”@Henk:我认为这是“不要过早优化”,而不是“永远不要优化,周期”。如果多个线程同时使用这段代码,我不认为每次访问都需要一个完整的内存屏障。此外,拥有32位处理器的PC机数量已经足够少了,而且只会越来越少。当然,我是在夸大其词,但你真的应该证明这是一个瓶颈。我假设Interlocked知道目标平台的需求,并且只在分析指向它之后才开始考虑这个问题。尽管我不知道你的代码,但我认为这是不可能的。这是x64抖动的固有特性。这些方法完全消失,您只得到一条CPU指令。XCHG用于写入,锁定CMPXCHG用于读取。高度优化,不是免费的。@Hans:谢谢!是的,我浏览了代码,发现Read
实际上是compareeexchange(ref值,0,0)代码>。我认为这是内在的,但真正困扰我的是记忆障碍。当然,不是像“给我不眠之夜”那样“打扰我”:。