C#任务总和变量

时间:2017-01-24 15:45:12

标签: c# task

我有以下任务,他们共享sum变量,最后总和应该是9,但我得到3.你能帮我解决一下吗?非常感谢。

int sum = 0;
Task t1 = Task.Factory.StartNew(() =>
{
    sum = sum + Computation();
});
Task t2 = Task.Factory.StartNew(() =>
{
    sum = sum + Computation();
});
Task t3 = Task.Factory.StartNew(() =>
{
    sum = sum + Computation();
});

Task.WaitAll(t1, t2, t3);
Console.WriteLine($"The sum is {sum}");

private static int Computation()
{
    return 3;
}

3 个答案:

答案 0 :(得分:5)

这是因为您正在同时从多个线程写入相同的字段。

使用System.Threading中的Interlocked.Add,这将阻止每个线程在同一时刻写入变量。

int sum = 0;
Task t1 = Task.Factory.StartNew(() =>
{
     Interlocked.Add(ref sum,Computation());
});
Task t2 = Task.Factory.StartNew(() =>
{
     Interlocked.Add(ref sum,Computation());
});
Task t3 = Task.Factory.StartNew(() =>
{
     Interlocked.Add(ref sum,Computation());
});

Task.WaitAll(t1, t2, t3);
Console.WriteLine($"The sum is {sum}");

答案 1 :(得分:0)

你永远不会告诉你的代码要等到任务't1'结束,直到你开始't2'等,所以一切都是并行执行的。每个线程读取“sum”中的值(最初为0)并添加3.所以0 + 3 = 3.之后它会回写3.所以代码完全按照你的编程来做。 Galister解释了如何添加锁定(关于此注释的一个注意事项:计算机中的操作几乎不会发生在完全同一时刻;)

答案 2 :(得分:0)

Interlocked类在需要原子操作时非常有用,但如果您关心性能,请考虑将其与Thread Local Storage (TLS)组合。

Parallel.For具有唯一的重载documantation

示例:

int sum = 0;
Parallel.For(1, 3,
    () => 0, //The type of the thread-local data.
    (x, state, tls) => // The delegate that is invoked once per iteration.
    {
        tls += x;
        return tls;
    }, 
    partial => //The delegate that performs a final action on the local state of each task.
    {
        Interlocked.Add(ref sum, partial);
    });