Interlocked.increment仍然没有解决价值缺失问题

时间:2011-04-16 23:46:33

标签: c# multithreading

我正在学习C#,目前正在学习线程。

这是一个在不同线程中多次向变量添加1的简单示例。

本书建议我可以使用Interlocked.increment(ref number)替换+= 1方法中的数字AddOne,因此该值将被锁定,直到它在线程中更新为止。因此输出将如预期的那样1000, 2000, ..... 10000。但我的输出仍为999, 1999, 2999, ...... 9999

只有在我取消注释Thread.Sleep(1000)行后,输出才会正确,但即使没有使用Interlocked

有谁能解释这里发生了什么?

static void Main(string[] args)
{
    myNum n = new myNum();

    for (int i = 0;i<10; Interlocked.Increment(ref i))
    {
        for(int a =1;a<=1000; Interlocked.Increment(ref a))
        {
            Thread t = new Thread( new ThreadStart( n.AddOne));
            t.Start();
        }

        //Thread.Sleep(1000);
        Console.WriteLine(n.number);
    }
}

class myNum
{            
    public int number = 0;

    public void AddOne()
    {
        //number += 1;
        Interlocked.Increment(ref number);
    }  
}

2 个答案:

答案 0 :(得分:4)

您将在所有线程执行完毕之前打印出该值。您需要在打印前加入所有线程。

for(int a = 0; a < 1000; a++)
  {
    t[a].Join();
  }

您需要将线程存储在数组或列表中。此外,您不需要任何for循环中的互锁指令。它们都只在一个线程(主线程)中运行。只有AddOne中的代码在多个线程中运行,因此需要同步。

答案 1 :(得分:0)

对我来说,使用此代码尝试实现的目标有点奇怪。您在任何地方都使用Interlocked.Increment而没有明确的需求。

访问可以从不同线程访问的值所需的

Interlocked.Increment。在您的代码中,它仅为number,因此您不需要ia,只需使用i++a++

您要求的问题是,您只是不要等待您启动的所有线程完成其工作。看看Thread.Join()方法。您必须等待所有线程开始完成其工作。

在这个简单的测试中,你完成了Thread.Sleep(1000);你做类似的等待,但假设所有线程在1000毫秒内完成是不正确的,所以只需使用Thread.Join()

如果您修改AddOne()方法以使其开始执行的时间更长(例如向其中添加Thread.Sleep(1000)),您会发现Thread.Sleep(1000);不再有用。

我建议您详细了解ThreadPool vs Threads。另请查看Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4