问题
I was trying to investigate a simple piece of code with two threads accessing a shared integer variable, one incrementing and the other decrementing it:
static int n = 0;
static void Main()
{
var up = new Task(() =>
{
for (int j = 0; j < 400000; j++)
++n;
});
up.Start();
for (int i = 0; i < 400000; i++)
--n;
up.Wait();
Console.WriteLine(n);
Console.ReadKey();
}
I've read a number of times that C# increment/decrement operations are not thread-safe and should be replaced with Interlocked.Increment and Decrement methods. That indeed works however I when I try to set a breakpoint and check the disassembly window, it looks as if the ++ and -- operators are atomic, their assembly equivalents are
inc dword ptr ds:[29A0C9Ch]
and
dec dword ptr ds:[29A0C9Ch]
respectively. So why is it then that the code above sometimes outputs a non-zero value?
回答1:
Because they are not atomic to start with: How come INC instruction of x86 is not atomic?
Interlocked synchronizes the caches on top and makes sure no interruption happens.
why is i++ not thread safe on a single core machine?
has some more details.
回答2:
So why is it then that the code above sometimes outputs a non-zero value?
Because inc and dec are not atomic. The processor will translate these into a lower-level instructions (e.g., inc
=> read + add + store)
来源:https://stackoverflow.com/questions/25238067/c-sharp-thread-safety-on-increment-decrement-operations