非阻塞与并行(TPL)的互锁使用问题

时间:2014-08-08 08:31:42

标签: c# multithreading task-parallel-library

我对多线程中代码的准确性感到困惑,因为有些时候我得到了错误的结果。

看起来可能会失败。以下是代码。

public class MyKeyValue
{
    public double Key { get; set; }
    public double Value { get; set; }
}

public class CollMyKeyValue : List<MyKeyValue>
{
    public void SumUpValues(CollMyKeyValue collection)
    {
        int count =0;
        Parallel.For(count, this.Count, 
        (i) => 
        {
            this[count].Value = this[count].Value + collection[count].Value;
            Interlocked.Increment(ref count);
        });  
    }
}

假设两个集合中的密钥相同。

我想将一个集合的值添加到另一个集合中。是安全吗?

我没有将this[count].Value = this[count].Value + collection[count].Value;放在线程安全块中。

2 个答案:

答案 0 :(得分:5)

只需删除互锁增量:

public void SumUpValues(CollMyKeyValue collection)
{
    //int count =0;
    Parallel.For(0, this.Count, 
        (i) => 
            {
                this[i].Value = this[i].Value + collection[i].Value;
                //Interlocked.Increment(ref count);
            });  
}

您的版本正在改变循环内的索引变量。 For循环自动执行此操作;在并行版本中,每个线程都要获得i(或i的集合),因此在循环中递增是没有意义的。

答案 1 :(得分:5)

不确定你要做什么。但我想你的意思是这个。

public void SumUpValues(CollMyKeyValue collection)
{
    Parallel.For(0, this.Count, (i) =>
    {
        this[i].Value += collection[i].Value;
    });
}

第一个参数表示Parallel.For从哪里开始,改变它是没有意义的。你得到i作为循环体的参数,它将告诉你你在哪个迭代。