我正想要在高吞吐量C++服务器中使用最佳数据结构。数据结构将被用来存储从几个到几百万个对象的任何东西,并且不需要排序(尽管可以非常便宜地提供独特的排序键)。要求是它可以支持高效的插入,理想情况下是O(1),中等效率的移除和高效的遍历。它不需要支持查找操作(除了可能需要删除)。并行数据结构设计
扭曲的是它在修改时必须是线程安全的,而其他线程正在枚举数据结构。这意味着一个简单的红黑树不起作用,因为一个线程不能插入一个元素(并执行必要的树旋转),而不会搞乱其他线程持有的任何光标。
它是而不是可接受的使用读/写锁,并推迟写操作,直到所有的读取器完成,因为读操作可能会很长寿。读者是否可以看到插入是否可见,这并不重要。
内存占用也很重要,而小显然更好!
有什么建议?
回应评论:
感谢您的答案。
不,插入无法使现有的迭代器无效。迭代器可能会或可能不会看到新插入,但是他们必须看到插入没有发生时他们会看到的所有内容。
需要删除,但是由于更高级别的规则,我可以保证迭代器永远不会停止在可删除的项目上。
为每个节点锁定游标会对性能产生太大的影响。一次可能有多个线程读取,多个线程在锁中使用的任何类型的内存热点都会导致内存带宽(正如我们发现的难题!)。即使是多线程调用InterlockedIncrement的读者的简单计数也无法顺利进行扩展。
我同意链接列表可能是最好的方法。删除是很少见的,因此为支持O(1)删除而支付内存处罚是很昂贵的,我们可以根据需要分别计算这些值,因为删除往往是批处理操作。
幸运的是,只要在改变头指针之前在插入的节点中更新指针,插入到链表中并不需要对读取器进行任何锁定。
锁复制解锁的想法很有趣。所涉及的数据量太大,无法用作读者的默认设置,但它可能会在作家与读者碰撞时使用。读/写锁可以保护整个结构,如果数据结构与读卡器发生冲突,写入操作会克隆数据结构。写入比读取要少得多。
可以插入无效现有的迭代器?如果是这样,那会让生活更轻松。你想支持删除吗?如果是这样,当一个线程删除正在被另一个线程读取的项目时,预期的行为是什么? – 2008-11-04 16:05:58
你的目标是什么?无锁或免等待数据结构? – user 2013-06-26 04:48:22