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