我正在编写具有单个编写器和多个读取器的并行代码。编写器将从头到尾填充数组,读者将按顺序访问数组的元素。伪代码类似于以下内容:
for(a while){
vec[producerIndex] = someStuff();
++producerIndex;
}
制作人主题:
while(!finished){
int myIndex = consumerIndex++;
while(myIndex >= producerIndex){ spin(); }
use(vec[myIndex]);
}
消费者主题:
{{1}}
我是否需要围绕producerIndex进行任何类型的同步?似乎可能发生的最糟糕的事情是,我会在更新时读取旧值,这样我可能会花费额外的时间。我错过了什么吗?我可以确定myIndex的每个作业都是唯一的吗?
答案 0 :(得分:4)
正如评论所指出的,这段代码有一个数据竞争。不要猜测代码是否有机会做你想做的事情,而是修复它:将producerIndex
和consumerIndex
的类型从int
更改为std::atomic<int>
并让编译器实现者和标准库实现者担心如何在目标平台上正常工作。
答案 1 :(得分:0)
阵列可能会存储在缓存中,因此所有线程都有自己的副本。每当生产者在数组中放入一个新值时,这将在存储地址上设置脏位,因此使用该值的每个其他线程都会将其从RAM中检索到缓存中自己的副本。 这意味着您将获得大量缓存未命中但没有竞争条件。 :)