【发布时间】:2026-01-26 21:30:01
【问题描述】:
我需要以只读方式几乎不断地迭代一系列结构,但对于每 1M+ 次读取,其中一个线程可能会附加一个项目。我认为在这里使用互斥锁会有点矫枉过正,我还在某处读到读/写锁对读者有其自身的缺点。
我正在考虑在 std::vector 上使用 reserve() 但这个答案 Iterate over STL container using indices safe way to avoid using locks? 似乎无效。
关于哪种方式可能最快的任何想法?最重要的是让读者能够在尽可能少的争用情况下快速有效地进行迭代。写入操作对时间不敏感。
更新:我的另一个用例是“列表”可以包含指针而不是结构。即,std::vector。同样的要求也适用。
更新 2:假设示例
全球可访问:
typedef std::vector<MyClass*> Vector;
Vector v;
v.reserve(50);
阅读器线程 1-10:(这些线程几乎一直在运行)
.
.
int total = 0;
for (Vector::const_iterator it = v.begin(); it != v.end(); ++it)
{
MyClass* ptr = *it;
total += ptr->getTotal();
}
// do something with total
.
.
编写器线程 11-15:
MyClass* ptr = new MyClass();
v.push_back(ptr);
这基本上就是这里发生的事情。线程 1-15 都可以同时运行,尽管通常只有 1-2 个读取线程和 1-2 个写入线程。
【问题讨论】:
-
这些向量有多大?它们必须是数组/向量吗?您需要内存块连续性吗?您可以将其更改为即元素列表或 1024 元素块列表等吗?
-
并发结构的数量是否有界?它们是否曾经被删除或原地变异,或者您真的只是一遍又一遍地读取相同的值?有多少读者?
-
@quetzalcoatl 向量的范围从大约 2-20 个项目,平均大约 7 个。它们不需要内存连续性,但我认为具有这种连续性可能更可取 w.r.t 缓存位置。我愿意接受任何建议。
-
好的,如果上面的大小没有限制,你就不能保留一个向量并且保证它永远不需要重新分配。所以,你需要一些可以成长的东西。多个“读者”可以同时尝试增加列表吗?
-
一种可能的方式:数据有一个读者副本和一个作者副本;读者阅读他们的副本,作者更新他们的副本(带锁);偶尔(比如每 10k 读者的迭代),读者的副本会从作者的副本中更新。读者将等到这完成。缺点是所有读者都必须等到最后一个读者完成其周期。如果读取器之间不需要始终保持一致性,那么每个读取器可以独立切换,但您将需要更多的数据副本。
标签: c++ performance stl locking