如何在Parallel.For中锁定数组以进行聚合

时间:2013-06-03 00:56:44

标签: c# .net multithreading locking

我正在尝试迭代2D数组,然后在Parallel.For中添加另一个2D数组的部分 环。 我已经找到了在循环内部进行累积的示例 单个变量,但我不知道该怎么做。 GridB正在进行积累,所以肯定需要锁定它作为其中的项目 从不同的线程添加 如果需要锁定,你怎么去锁定整个数组?

int[,] GridA = new int[D + 2, D + 2];
int[,] GridB = new int[D + 2, D + 2];

Parallel.For(1, D+1 , r =>
{
for (int c = 1; c <= D ; c++)
    if (GridA[r, c] != 0)
    {
        int v = GridA[r, c];

        GridB[r - 1, c - 1] += v;
        GridB[r - 1, c] += v;
        GridB[r - 1, c + 1] += v;

        GridB[r, c - 1] += v;
        GridB[r, c + 1] += v;

        GridB[r + 1, c - 1] += v;
        GridB[r + 1, c] += v;
        GridB[r + 1, c + 1] += v;
    }
});

1 个答案:

答案 0 :(得分:1)

您可以像这样锁定GridB

Parallel.For(1, D+1 , r =>
{
  for (int c = 1; c <= D ; c++)
  {
    if (GridA[r, c] != 0)
    {
      int v = GridA[r, c];
      lock(GridB) 
      { 
        GridB[r - 1, c - 1] += v;
        // etc.
      }
    }
  }
});

但是,您正在序列化对GridB的所有访问,这类访问会破坏使用多个线程的目的。

如果您只想为每个元素添加固定值,Interlocked.Add命名空间中的System.Threading将以原子方式执行添加,因此您无需取消锁定整个阵列。

以下是用法示例:

Parallel.For(1, D+1 , r =>
{
    for (int c = 1; c <= D ; c++)
      if (GridA[r, c] != 0)
      {
         int v = GridA[r, c];

          Interlocked.Add(ref GridB[r - 1, c - 1], v);
          // rinse, repeat
      }
}