【问题标题】:Lock free doubly linked skip list无锁双链跳过列表
【发布时间】:2012-02-08 20:58:46
【问题描述】:

存在大量关于无锁双向链表的研究。同样,在无锁跳过列表上也有大量研究。然而,据我所知,没有人管理过无锁的双向链接跳过列表。有没有人知道任何相反的研究,或者是这种情况的原因?

编辑: 具体场景是构建一个快速分位数(50%、75% 等)累加器。样本在 O(log n) 时间内被插入到跳过列表中。通过维护当前分位数的迭代器,我们可以在 O(1) 时间内将插入的值与当前分位数进行比较,并且可以轻松确定插入的值是在分位数的左侧还是右侧,以及分位数的多少结果需要移动。左移需要前一个指针。

据我了解,面对同时插入和删除的多个线程,任何困难都来自于保持先前的指针一致。我想这个解决方案几乎肯定会巧妙地使用指针标记。

【问题讨论】:

  • 所以每次你向列表中添加一个项目时,你想去调整你的分位数数据,以便每个分位数知道它的起始值、范围以及指向分位数中起始项目的指针?我猜,如果跳过列表是脏的,那么根据请求计算分位数信息是不是太慢了?
  • @johnnycrash 每次插入时,您都知道每个分位数的值,因此您知道新值是否大于或小于分位数,以及分位数是否需要向前或向后移动由一个单位。我不确定您所说的范围是什么意思;分位数始终是单个值。在我最终使用的方案中,skip-list 方法的常数因子高于朴素方法,但随着操作数量的增加,它的扩展性非常好。每次插入更新分位数的成本是恒定的。

标签: lock-free doubly-linked-list skip-lists


【解决方案1】:

但是你为什么要这样做呢?我实际上并没有坐下来弄清楚跳过列表是如何工作的,但根据我的模糊理解,你永远不会使用前面的指针。那么为什么会有维护它们的开销呢?

但如果你愿意,我不明白你为什么不能。只需将单链表替换为双链表即可。双向链表在逻辑上是连贯的,所以都是一样的。

【讨论】:

    【解决方案2】:

    我有一个想法给你。我们使用“光标”在跳过列表中查找项目。光标还保留了到达该项目的轨迹。我们使用这条线索进行删除和插入——它避免了执行这些操作的第二次搜索,并且它嵌入了在进行遍历时看到的列表的版本号。我想知道您是否可以使用光标更快地找到上一项。

    您必须在光标上上一级,然后搜索仅比您的项目少一点的项目。或者,如果搜索到了链表的最低级别,只需在遍历时保存 prev ptr。最低级别可能有 50% 的时间用于查找您的项目,因此性能会不错。

    嗯...现在想来,光标似乎有 50% 的时间有 prev ptr,25% 的时间需要从 1 级向上再次搜索,12.% 2 级向上等. 因此,在极少数情况下,您几乎必须完全重新进行搜索。

    我认为这样做的好处是您不必弄清楚如何“无锁”维护一个双链跳过列表,并且在大多数情况下,您可以显着降低定位前一个项目的成本。

    【讨论】:

    • 跳过列表通常有一个静态的最大高度,因此搜索操作可以填充一个指针数组,指向在每个级别遍历的最右边节点。
    【解决方案3】:

    作为维护反向链接的替代方法,当需要更新分位数时,您可以进行另一次搜索以查找其键小于当前键的节点。正如我刚刚在对 johnnycrash 的评论中提到的那样,可以构建在每个级别找到的最右边节点的数组 - 并且可以由此加速第二次搜索。 (Fomitchev 的论文提到这是一种可能的优化。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-15
      • 2015-02-02
      • 2017-04-03
      • 2010-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多