Can the compiler or processor reorder the following instructions so that another Thread sees a == 0
and b == 1
?
Assuming int a = 0, b = 0;
somewhere.
System.Threading.Interlocked.CompareExchange<int>(ref a, 1, 0);
System.Threading.Interlocked.CompareExchange<int>(ref b, 1, 0);
No. Using Interlock
will signal a full memory fence. “That is, any variable writes before the call to an Interlocked
method execute before the Interlocked
method, and any variable reads after the call executes after the call.” [1] They use volatile read/write methods to prevent the b = 1
before a = 1
.
[1]: Jeffrey Richter: “CLR via C# - Third Edition” part V Threading, page 803
You are reading too much theory. Yes it can happen in practice if the other thread does
Console.WriteLine("a: {0}, b: {1}", a, b);
Since String.Format which is used to format the string has a signature of
String Format(string fmt, params object[] args)
{
....
}
your integers will get copied because of boxing. The only condition which needs to be true is that the threads time slice ends when it has copied a in its unitialized state. Later when the thread resumes work both variables are set to one but your Console output will be
a: 0, b: 1
The point of seeing other values happens immediately if you are working with copies of values without realizing it. That is the reason why you let usually other people write correct lock free code. If try you debug lock free code with Console.WriteLine I wish you good luck with it.
Although a and b are set in order (I do not think the JIT compiler will reorder your interlocked calls) you have no guarantee that other threads see only two zeros or two ones. You could try to read first b and check if it has the value one then you can deduce the value of a but in that case you would not even need the value of a anyway. That should be true at least for the x86 memory model. That assumption can be broken by weaker memory models such as ARM.
Sure it can. The individual operations that compose the CompareExchange
operation cannot be observably re-ordered, but the two calls to CompareExchange
can be reordered from the perspective of another thread, so long as the thread executing this code cannot observe such behavior.
The synchronization tools in place for CompareExchange
are preventing observable reordering between the operations affecting the memory locations relevant to that operation, not any operations in general, nor is there anything in that code to prevent the compiler or JITter from reordering these two CompareExchange
calls entirely (from the perspective of another thread).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With