Note that there are some explanatory texts on larger screens.

plurals
  1. POhow incrementing a shared value from several threads affine to one CPU manages to produce correct results with ++ being three instructions?
    text
    copied!<p>I thought I know a lot on the subject, but the following puzzles me. I know that on the particular PC I run this on, "_x++" is translated to three assembly instructions (move value to register from memory, increment in register, write back to memory). So why on Earth, when locked to a single CPU the threads incrementing the value manage to not be preempted at the exact time when a value is incremented, but still in a Register and not written back to memory? Does anybody know an answer to this? I'm guessing this works by sheer luck, but I can't exactly prove it.</p> <p>I was able to make the correct result go away by setting a break point on <code>inc eax</code> in the disassembly window in VS, then making a few steps in the debugger, but that's no proof. Not a solid one.</p> <p>[This code IS NOT THREAD-SAFE on purpose. This is not production code, it serves educational purposes. I'm trying to dig deep into the subject. Of course, with cache lines out of the picture, we get a lot, but still -- three instructions, and not even a single miss, that's weird! This is a 4 core CPU, x64.]</p> <pre><code>{ private static int NumberOfThreads = 2; private const long IncrementIterations = 1000000000; private static int _x; static void Main(string[] args) { Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1; Console.WriteLine("Hit Enter"); Console.ReadLine(); while (true) { var barrier = new Barrier(NumberOfThreads); _x = 0; var threads = new List&lt;Thread&gt;(); for (int i = 0; i &lt; NumberOfThreads; i++) { var thread = new Thread( delegate() { barrier.SignalAndWait(); for (int j = 0; j &lt; IncrementIterations; j++) { _x++; } }); thread.Start(); threads.Add(thread); } BlockUntilAllThreadsQuit(threads); Console.WriteLine(_x); Console.WriteLine("Actual increments: " + (IncrementIterations * NumberOfThreads)); if (_x != (IncrementIterations * NumberOfThreads)) { Console.WriteLine("Observed: " + _x); break; } } Console.ReadLine(); } private static void BlockUntilAllThreadsQuit(IEnumerable&lt;Thread&gt; threadsToWaitFor) { foreach (var thread in threadsToWaitFor) { thread.Join(); } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload