使用并行扩展时是否需要关注MemoryBarrier?
编辑-由于最初的问题是开放式的,所以要详细说明:(@xanatos的答案是我正在寻找的答案)
举一个具体的例子:假设我使用Parallel.ForEach,每次迭代都会设置类中某个属性的值(每次迭代都设置自己的特定属性,没有两次迭代设置同一属性的值)。在调用Parallel.ForEach的同一个线程上,我访问从Parallel.ForEach.
class Program
{
static void Main(string[] args)
{
var t = new Test();
t.InitializePropertiesInParallel();
var a = t.PropA; // Could never be 0?
var b = t.PropB; // Could never be 0?
}
}
public class Test
{
public int PropA { get; set; }
public int PropB { get; set; }
public void InitializePropertiesInParallel()
{
var initializers = new List<Action<int>>()
{
i => PropA = i,
i => PropB = i
};
initializers.AsParallel().ForAll(a => a(1));
}
}
请记住一件事:缓存行无效。这是一个复杂的主题,但这里有一篇很棒的MSDN文章。
在这个特定的例子中,它的要点是,因为你正在从两个不同的线程修改同一个对象实例,即使你没有接触到内存中完全相同的位置,你也会接触到同一条缓存线,因此当处理器1上的第一个线程更改内存时,在处理器2可以再次读取/写入之前,缓存将被刷新和更新。
也就是说,再次考虑到你只有两个道具的具体例子,这是一个微观优化,绝对不需要担心。如果你要对其进行推断,需要注意的是。
如果每个工作者都不需要其他工作者准备的数据(因此不存在工作者1写入A而工作者2读取A的情况),则不需要MemoryBarrier
。当所有任务完成时,有一个Wait
充当MemoryBarrier
(最终,即使您没有看到它,在某个地方也有一个同步结构等待所有工作人员完成)