Reputation: 13121
Example:
Thread a: Interlocked.Increment(ref x);
Thread b: int currentValue = x;
Assuming thread b executes after thread a, is "currentValue" in thread b guaranteed to be the incremented value? Or, does thread b need to do a Thread.VolatileRead(ref x)?
Upvotes: 5
Views: 322
Reputation: 1062745
As I understand it, Interlocked is only guaranteed when accessed by other Interlocked methods. This may be especially important when talking about 64-bit values on x86 systems, where it cannot be guaranteed to be atomic, so torn values are a concern. A good trick for robustly reading a value that can be changed by Interlocked is CompareExchange:
int val = Interlocked.CompareExchange(ref field, 0, 0);
This mutates the value of field
to 0, but only if the old value was 0 - otherwise it does nothing. Either way the old value is returned. So basically: it reads the value without ever changing it, and is safe vs other Interlocked methods.
Upvotes: 3
Reputation: 150108
Technically that depends on the CPU .NET is running on, but for any common CPU the answer is yes, cache coherency is guaranteed for an Interlocked.Increment. It acts as a memory barrier as required by MESI.
a CPU can have in its cache a line which is invalid, but where it doesn't yet know that line is invalid - the invalidation queue contains the invalidation which hasn't yet been acted upon. (The invalidation queue is on the other "side" of the cache; the CPU can't scan it, as it can the store buffer). As a result, memory barriers are required.
http://en.wikipedia.org/wiki/MESI_protocol (x86)
MOESI (used on AMD64 chips) is quite similar:
http://en.wikipedia.org/wiki/MOESI_protocol (AMD64)
Upvotes: 5