OK, I think I should clarify something about what I said in regards to all of the Microsoft JIT’ed assignments are volatile. Yes, that is a true statement, but you cannot simply take that out of context and say “Well, then that means that all of my assignments are safe”. Yes, they will be, but that doesn’t mean that it will operate the way you think it does. Take for instance the following code snippet:
Char[] cArr = new Char[20];
public void Func()
{
object secondRef = cArr;
if (secondRef == cArr)
{
if (secondRef == cArr)
return;
}
}
Upon first glance, you might think that, “Well, since my assignments are all volatile, there’s nothing wrong with this code. The surprise comes in when you look at the JIT’ed IL:
public void Func()
{
object secondRef = cArr;
00000000 mov edx,dword ptr [ecx+4]
00000003 mov eax,edx
if (secondRef == cArr)
00000005 cmp eax,edx
00000007 jne 00000009
00000009 ret
}
You’ll notice that the code is optimized and stores the first object reference inside a register with the intent of not having to check the memory location subsequent times (this is the optimization). So now, let’s decorate the array with the volatile keyword. You immediately notice that the JITer no longer stores any previous addresses of the array inside a register. Each comparison call will get the array address from memory:
public void Func()
{
object secondRef = cArr;
00000000 mov eax,dword ptr [ecx+4]
if (secondRef == cArr)
00000003 cmp eax,dword ptr [ecx+4]
00000006 jne 0000000B
{
if( secondRef == cArr )
00000008 cmp dword ptr [ecx+4],eax
0000000b ret
}
If you omit the volatile keyword, the second check is simply removed and a register compare is performed with the previously determined address of the array. When you add the volatile keyword the cmd eax,edx becomes cmp eaxdword ptr[ecx+4] which in works like a memory barrier. So even though Microsoft’s JITer makes every assignment volatile, you HAVE to keep in mind what type of optimizations occur.