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
写入值,后者稍后由调用线程读取。在传递给Parallel.For
的lambda内部,没有明确的锁定数组读取和写入。因为这个例子来自于Microsoft,我认为它是线程安全的,但我正在尝试理解背后发生了什么使其线程安全。据我所知,从我阅读的内容和在SO上提出的其他问题(例如this one),需要几个内存屏障才能使所有这些工作正常。这些是:
- 在创建和初始化
matA
和matB
之后,在调用线程上设置内存屏障。 - 在从
matA
和matB
读取值之前,在每个非调用线程上设置内存屏障。 - 在向
result
写入值之后,在每个非调用线程上设置内存屏障。 - 在从
result
读取值之前,在调用线程上设置内存屏障。
我理解得对吗?
如果是这样,那么Parallel.For
是否会以某种方式执行所有这些操作?我查看了参考源代码,但很难跟踪代码。我没有看到任何lock
块或MemoryBarrier
调用。