C#增加/减少操作的线程安全性

时间:2014-08-11 07:39:29

标签: c# multithreading thread-safety

我试图调查一段简单的代码,其中两个线程访问一个共享整数变量,一个递增,另一个递减它:

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();
}

我已经多次读过C#递增/递减操作不是线程安全的,应该用Interlocked.Increment和Decrement方法替换。这确实有效但是当我尝试设置断点并检查反汇编窗口时,看起来好像++和 - 运算符是原子的,它们的程序集等价物是

inc dword ptr ds:[29A0C9Ch]

dec dword ptr ds:[29A0C9Ch]

分别。 那么为什么上面的代码有时输出一个非零值呢?

2 个答案:

答案 0 :(得分:2)

因为它们不是原始的:How come INC instruction of x86 is not atomic?

Interlocked在顶部同步缓存并确保不会发生中断。

why is i++ not thread safe on a single core machine?

有更多细节。

答案 1 :(得分:1)

  

那么为什么上面的代码有时会输出一个非零值?

因为inc and dec are not atomic。处理器会将这些转换为较低级别的指令(例如,inc =&gt;读取+添加+存储)