即使在线程中使用Join()后得到不同的答案 - C#

时间:2015-07-01 12:49:05

标签: c# multithreading methods

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Collections.ObjectModel;
using System.Threading;
namespace JUSTFORPRACTICE
{
class Program
{
    static int total = 0;
    public static void Main()
    {
        Thread t1 = new Thread(fun);
        t1.Start();
        Thread t2 = new Thread(fun);
        t2.Start();
        Thread t3 = new Thread(fun);
        t3.Start();
        t1.Join();
        t2.Join();
        t3.Join();
        Console.WriteLine(total);
    }
    public static void fun()
    {
        for (int i = 1; i <= 10000; i++)
            total++;
    }
}

}

我已经读过使用Join()我们可以阻止主线程执行进一步的语句,直到当前线程在运行。但是每次当我运行时我得到不同的输出.....为什么?

1 个答案:

答案 0 :(得分:4)

您有三个并发运行的线程,所有线程都以不安全的方式改变共享状态:

  • 增量不是原子的,因为它是&#34;读取,局部递增,写入&#34; - 如果多个线程读取相同的值,然后每个线程在本地递增,然后写入,您将有效地“丢失”#34;除了其中一个增量之外的所有增量。
  • 没有内存障碍可以强制每个线程从主内存中读取变量的最新值,或者立即将结果返回写入主内存。每个线程可以执行fun作为&#34;从主存储器读取一次到寄存器;将寄存器递增10001次;将结果写回主内存&#34; ...

如果将total++更改为Interlocked.Increment(ref total),则每个增量操作都将是原子的,并且保证可以处理新数据,并且结果立即对所有线程可见。

问题的道德:在处理来自多个线程的可变共享数据时要非常小心。