Interlocked.increment 仍然没有解决值丢失的问题

发布于 2024-11-02 00:11:01 字数 940 浏览 0 评论 0原文

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

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

这本书建议我可以使用 Interlocked.increment(ref number) 来替换 AddOne 方法中的数字 += 1 ,因此该值将被锁定,直到它在线程内更新。因此输出将如预期的那样为 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);
    }  
}

I'm studying C# right now and currently learning threading.

Here is a simple example to adding 1 to a variable multiple times within different threads.

The book suggested I can use Interlocked.increment(ref number) to replace the number += 1 within the AddOne method, therefore the value will be locked until it's updated within the thread. So the output will be 1000, 2000, ..... 10000 as expected. But My output is still 999, 1999, 2999, ...... 9999.

Only after I uncomment the Thread.Sleep(1000) line will the output be correct but even without the Interlocked been used.

Can anyone explain what's happening here?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

极致的悲 2024-11-09 00:11:01

您将在所有线程完成执行之前打印出该值。您需要在打印之前连接所有线程。

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

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

You are printing out the value before all of the threads have finished executing. You need to join all of the threads before printing.

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

You'll need to store the threads in an array or list. Also, you don't need the interlocked instruction in any of the for loops. They all run in only one thread (the main thread). Only the code in AddOne runs in multiple threads and hence needs to by synchronized.

笑红尘 2024-11-09 00:11:01

对我来说有点奇怪你想用这段代码实现什么。您在任何地方都使用 Interlocked.Increment 而没有明确的需要。

访问可从不同线程访问的值需要 Interlocked.Increment。在您的代码中,它只是 number,因此您不需要将其用于 ia,只需照常使用 i++< /code> 和 a++

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

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

如果您修改 AddOne() 方法,使其开始执行更长的时间(例如向其中添加 Thread.Sleep(1000)),您会注意到 Thread. Sleep(1000); 不再有帮助了。

我建议阅读有关线程池与线程的更多信息。另请查看 并行编程模式:使用 .NET Framework 4 理解和应用并行模式

It a bit strange for me what you trying to achieve with this code. You are using Interlocked.Increment everywhere without explicit needs for it.

Interlocked.Increment required for access to values which can be accessed from different threads. In your code it is only number, so you don't require it for i and a, just use as usually i++ and a++

The problem you are asking for is that you just don't wait for all threads you started are completed its job. Take a look to Thread.Join() method. You have to wait while all of threads you are started completes its work.

In this simple test you are done with Thread.Sleep(1000); you do similar wait but its not correct to assume that all threads are complete in 1000 ms, so just use Thread.Join() for that.

If you modify your AddOne() method so it starts to executes longer (e.g. add Thread.Sleep(1000) to it) you'll notice that Thread.Sleep(1000); doesn't help any more.

I'll suggest to read more about ThreadPool vs Threads. Also take a look to Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文