I admit, I want to be a Craftsman
Developers have long discussed and debated whether programming is an art, a science, an engineering practice, or something else. I don’t believe in Black and...
Wait... how is this possible? Did we lose updates? Did I not call the method enough times? This surely must be a horrendous bug in the .NET Framework! Damn Bill and his blasted company. Trust me, it's not a bug. There's a good explanation of this behavior.
If you haven't written a lot of multithreaded code yet, the problem with the above code may not be obvious. Truth be told, there really isn't a problem with the code... IF you are only running the code on a single thread ever. But the likelihood of running on a single thread is becoming smaller and smaller. And as you can see, when we are running this in a multithreaded environment, there is most definitely a problem with the code.
A lot of .NET developers look at "TotalMessages++" and interpret it as one line of code, one execution, one instruction, etc. But there's the rub, it isn't. The code "TotalMessages++" is actually four instructions when compiled down to IL.
1: L_0001: ldsfld int32 CSharpSandbox.Logger::TotalMessages
2: L_0006: ldc.i4.1
3: L_0007: add
4: L_0008: stsfld int32 CSharpSandbox.Logger::TotalMessages
These four lines essentially say the following:
Now let's imagine two threads executing the four steps above at the same time. Since threads won't be in perfect lock-step, they may be off by two steps (assuming the value of TotalMessages is currently 2):
[Thread 1] 1. Get the current value of TotalMessages (gets 2)
[Thread 1] 2. Get the value 1
[Thread 2] 1. Get the current value of TotalMessages (gets 2)
[Thread 2] 2. Get the value 1
[Thread 1] 3. Add the two numbers together (2 + 1)
[Thread 1] 4. Save the result back into TotalMessages (saves 3)
[Thread 2] 3. Add the two numbers together (2 + 1)
[Thread 2] 4. Save the result back into TotalMessages (saves 3)
So we've executed that code twice and at the end of the execution, TotalMessages has only increased by one. This is exactly what a race condition is. It's that simple. It's not as advanced as a concept as one might think.
This is why developers need to understand what race conditions are. A snippet of code that looks completely innocuous can cause some big problems when run in a multithreaded development. While future technologies will make writing parallel code easier, it won't prevent these types of problems from occurring. You still need to be aware of some of the common Threading 101 concerns/topics that exist today.