【问题标题】:Interrupt-safe set scan中断安全集扫描
【发布时间】:2011-08-31 15:24:26
【问题描述】:

我需要一个满足这些有点不寻常的 (AFAIK) 要求的数据结构:

  1. 支持的操作有 Insert(set, item)、Delete(set, item) 和 ForAll(set, operation)
  2. 插入和删除是很少见的操作。该集合通常只包含一项。
  3. 在 C 中实现必须是可行的;特别是,不会为您收集垃圾。
  4. ForAll 必须能够安全地执行异步信号处理程序,其调用可能中断了插入或删除。

当然,最后一个要求是杀手锏。我有一个玩具实现,它在全局链表周围抛出一个全局锁,但是如果信号处理程序中断一个关键部分,那将会死锁。

(我知道在信号处理程序中执行 any 代码的所有问题;出于这个问题的目的,让我们专注于如何使 ForAll 崩溃和死锁安全(当它可能发生时)中断了插入或删除。)

【问题讨论】:

    标签: c algorithm data-structures concurrency


    【解决方案1】:

    如果集合通常很小,因此在 Insert 和 Delete 方法中列表的线性搜索足够快,那么您可以使用使用比较和交换的无锁链表实现。搜索给出了许多解释和示例。

    http://www.google.com/search?q=lock+free+linked+list

    对列表的所有更新都是作为原子操作(比较和交换)完成的,因此中断不会导致问题。

    【讨论】:

    • 谢谢,但我希望得到更具体和更有针对性的答案。我已经阅读了其中几篇论文;他们专注于使 Insert 和 Delete 对 彼此 无锁,而忽略 ForAll。我可以很好地将 Insert 和 Delete 相互锁定(实际上,做任何其他事情似乎都是不必要的复杂性,因为列表很短),但这对 ForAll 没有帮助。
    • 我想我可能遗漏了一些东西,但看起来reference.kfupm.edu.sa/content/l/o/… 的论文非常有效地解决了遍历问题。
    • 我接受这个,因为它在一般情况下是正确的答案,但为了记录,我最终做的是在插入和删除操作中调用sigprocmask,防止他们与信号处理程序。
    【解决方案2】:

    我确信 Jim 的方法很好,但是对于小集合和不频繁更新,您可能会更乐意实现最简单的软件事务内存形式。

    1. 读取指向当前结构版本的指针。
    2. 复制该版本并进行更新。
    3. 更新中的比较和交换。如果 CAS 失败,请返回步骤 1。

    异步扫描很简单——即读即走。如果没有垃圾收集,您将需要使用 Jim 链接的论文中的 SafeRead 和 Release 之类的东西。

    【讨论】:

    • 如果我没记错的话,这是Read-Copy-Update
    • 这在我工作的环境中是不可行的,因为无法知道 RCU“宽限期”何时过去。
    猜你喜欢
    • 2020-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-29
    • 2020-06-22
    • 1970-01-01
    相关资源
    最近更新 更多