Microsoft 的 Parallel.For 文档包含以下方法:
static void MultiplyMatricesParallel(double[,] matA, double[,] matB, double[,] result)
{
int matACols = matA.GetLength(1);
int matBCols = matB.GetLength(1);
int matARows = matA.GetLength(0);
// A basic matrix multiplication.
// Parallelize the outer loop to partition the source array by rows.
Parallel.For(0, matARows, i =>
{
for (int j = 0; j < matBCols; j++)
{
double temp = 0;
for (int k = 0; k < matACols; k++)
{
temp += matA[i, k] * matB[k, j];
}
result[i, j] = temp;
}
}); // Parallel.For
}
matA
在此方法中,可能有多个线程从和读取值matB
,这些值都是在调用线程上创建和初始化的,并且可能有多个线程将值写入result
,稍后由调用线程读取。在传递给 的 lambda 中Parallel.For
,数组读取和写入没有显式锁定。因为这个例子来自微软,所以我认为它是线程安全的,但我试图了解幕后发生的事情以使其成为线程安全的。
据我所读的内容和我在 SO 上提出的其他问题(例如这个),据我所知,需要几个内存屏障才能使这一切正常工作。那些是:
- 创建和初始化
matA
and后调用线程上的内存屏障matB
, matA
在从和读取值之前,每个非调用线程上的内存屏障matB
,- 在将值写入 后,每个非调用线程上的内存屏障
result
,以及 - 在从 读取值之前调用线程上的内存屏障
result
。
我是否正确理解了这一点?
如果是这样,是否Parallel.For
会以某种方式完成所有这些工作?我去挖掘参考源,但在遵循代码时遇到了麻烦。我没有看到任何lock
阻塞或MemoryBarrier
呼叫。