Is Interlocked.Read(ref long)
"optimized away" on 64-bit architectures? I.e. if I am writing a library which could be used by both architectures, should I be concerned about performance impact of using Interlocked.Read
unnecessarily on 64-bit CPUs?
I thought about using something like this, so I am wondering if this makes sense:
// 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
}
Yes, you are concerned unnecessarily of the performance impacts of Interlocked
because Interlocked
doesn't just perform an atomic action on values, it also ensures that the value is visible to all threads (sequential consistency). Let me explain.
On some architectures (some 64-bit architectures included) the value written to a memory location may be cached to improve performance. Simply reading a value may not read the "latest" value written by another thread despite being an atomic operation. Interlocked
also performs a memory fence so that any operations prior to the fence have any cached values flushed to actual memory.
So, while you might improve performance a minuscule amount, you're also introducing potential race conditions. On architectures where this isn't an issue, Interlocked
will not perform the extra work and does the optimization for you.
Unfortunately the documentation for Interlocked
is still not quite up to par on these details. See http://www.albahari.com/threading/part4.aspx for more details on the fence involved in Interlocked
operations.