Answering this question made me think about something is still not clear for me. Let's first assume we read all from this post and this post.
[begin edit] Maybe it's not so obvious (Italian humor?!) but title is just pretty provocative: of course there should be a reason if volatile
has been included in C#, I just can't understand exact one.[end edit]
In short we know we have three tools to share a variable between threads:
lock
because this will prevent instruction reordering.volatile
because will force CPU to always read value from memory (then different CPUs/cores won't cache it and they won't see old values).- Interlocked operations (
Increment
/Decrement
andCompareExchange
) because they'll perform change + assignment in a single atomic (fastfaster than, for example, a volatile + lock) operation.
What I don't understand (C# specs reference would be appreciated):
- How lock will prevent cache problem? Is it implicit a memory barrier in a critical section?
- Volatile variables can't be local (I read something from Eric Lippert about this but I can't find that post now and I don't remember his comments and - to be honest - I didn't even understand it very well). This makes me think they're not implemented with an
Interlocked.CompareExchange()
and friends, in what they're different?
What volatile
modifier will do for example in this code?
volatile int _volatileField = 0;
int _normalField = 0;
void test()
{
Interlocked.Increment(ref _normalField);
++_volatileField;
}
[begin edit] previous example involves atomic read + write, let's change it to _volatileField = 1;
, here I'm not talking about atomic operations. [end edit]
Moreover what compiler (beside warnings) will do here:
Interlocked.Increment(ref _volatileField);
They seems pretty different things (as I would imagine they are) but for my understanding Interlocked.Increment()
operand should implicitly be volatile (then it'll add just atomic increment). How is it possible for non volatile fields? Does they imply barriers too? Doesn't this hurt performance a lot (compared to volatile)?
If volatile
doesn't imply barriers but others do then why we can't use them as on local variables? Especially when used in, for example, parallel loops this will hurt performance in a significant way (I'm thinking about small functions with little code that work on a lot of data where data cache may be well used).
[begin edit] I found previous sentence was really unclear (sorry for my English). What I mean is: if performance (of volatile
compared to CompareExchange
, where comparison is applicable) are better (yes we can measure and in some scenario difference is measurable and visible) then why we can't use them for local variables? I'm thinking about parallel loops that manipulates a lot of data (where both overhead and barriers may hurt performance a lot).[end edit]