今天在MSDN的Interlocked.Increment 方法 (Int32) 的示例中看到两个变量经过“相同的”运算后,最后结果却不同,貌似理由是线程安全什么的 ,不太懂。现在把例子的代码贴出来了,请高手分析一下 为什么SafeInstanceCount和UnsafeInstanceCount两个变量的值不同??!! 我怎么感觉肯定相同呢!!唉  越来越发现自己编程学的好差!
例子如下:下面的代码示例说明增加和减少整数值的线程安全方式。SafeInstanceCount 始终为 0。但是 UnsafeInstanceCount 不一定为 0,因为在增加和减少计数之间会出现争用条件。此效果在多处理器计算机上尤其明显。using System;
using System.Threading;class Test
{
    static void Main()
    {
        Thread thread1 = new Thread(new ThreadStart(ThreadMethod));
        Thread thread2 = new Thread(new ThreadStart(ThreadMethod));
        thread1.Start();
        thread2.Start();
        thread1.Join();
        thread2.Join();        // Have the garbage collector run the finalizer for each
        // instance of CountClass and wait for it to finish.
        GC.Collect();
        GC.WaitForPendingFinalizers();        Console.WriteLine("UnsafeInstanceCount: {0}" +
            "\nSafeCountInstances: {1}",
            CountClass.UnsafeInstanceCount.ToString(),
            CountClass.SafeInstanceCount.ToString());
    }    static void ThreadMethod()
    {
        CountClass cClass;        // Create 100,000 instances of CountClass.
        for(int i = 0; i < 100000; i++)
        {
            cClass = new CountClass();
        }
    }
}class CountClass
{
    static int unsafeInstanceCount = 0;
    static int   safeInstanceCount = 0;    static public int UnsafeInstanceCount
    {
        get {return unsafeInstanceCount;}
    }    static public int SafeInstanceCount
    {
        get {return safeInstanceCount;}
    }    public CountClass()
    {
        unsafeInstanceCount++;
        Interlocked.Increment(ref safeInstanceCount);
    }    ~CountClass()
    {
        unsafeInstanceCount--;
        Interlocked.Decrement(ref safeInstanceCount);
    }
}

解决方案 »

  1.   

    ++操作其实是两个过程,
    a++等同于
    a = a+1;
    这里面需要先把a的值取出来,然后加1,然后再把值赋给a
    对于CPU来说这是两个过程,把a的值读出来,放到寄存器,累加,再把寄存器里的值读出来,赋值给a。
    如果这个过程被打断会发生什么呢,以下的两个a++在不同线程中
    a= 0;
    a++;
    a++;
    第一个a++进行到给a赋值之前被打断,此时寄存器里的值是1。然后执行第二个a++。第二个a++执行之后a的值是1,然后切换回第一个给a赋值的阶段,相当于把之前算好的1赋值给a,所以两次a++之后a的值竟然是1.
      

  2.   

    首先你一定得知道这个概念,在c#中绝大多数的操作都不是原子的。
    即使像简单的变量自增操作 a++,也不是原子的。
    即这个 a++的操作有可能不是在一个时间片中执行完成的,执行a++的操作可能会被其它线程抢占。
    而在此之间它没有预见到其它线程可能已经修改了a本身的值Interlocked.Increment(ref safeInstanceCount)操作,或lock就是为了解决这个问题的。
    让该操作原子完成,不被其它线程抢占。
      

  3.   

    首先你一定得知道这个概念,在c#中绝大多数的操作都不是原子的。
    即使像简单的变量自增操作 a++,也不是原子的。
    即这个 a++的操作有可能不是在一个时间片中执行完成的,执行a++的操作可能会被其它线程抢占。
    而在此之间它没有预见到其它线程可能已经修改了a本身的值Interlocked.Increment(ref safeInstanceCount)操作,或lock就是为了解决这个问题的。
    让该操作原子完成,不被其它线程抢占。
      

  4.   

    谢谢HttpResponse和wddw1986的精彩回答!!!!!!
       谢谢!!!看了你们的指点 貌似我明白了些 呼呼~~