【问题标题】:Singly-linked list insertion synchronization单链表插入同步
【发布时间】:2011-07-05 17:00:21
【问题描述】:

假设我有一个 N 个不重复的整数的排序单链表和 k 个线程(其中 k N),每个都试图将一些整数(大于头节点)插入到列表中。

是否可以将插入同步到这样的列表中:

  • 线程只能阻止对其(立即)前一个节点的访问
    (不锁定“整个列表”)
  • 最多可以使用 O(k) 个互斥锁和条件变量
  • 不得发生抢占/中断

?

【问题讨论】:

  • 家庭作业?面试题?你做了什么来尝试自己回答这个问题?这和 C 有什么关系?
  • 我正在做一个个人项目,我目前面临的问题(更复杂)减少到我上面提出的问题。我正在尝试在 C 中使用 pthreads 来实现解决方案,这就是我添加 c-tag 的原因。我应该提供更多的实现细节吗?

标签: c synchronization sorted singly-linked-list


【解决方案1】:

首先,如果插入集合不是一项非常罕见的任务,那么链表就不是一个很好的解决方案——因为找到插入点是一个O(N) 操作,即使对于排序列表也是如此,因此最终会严重扩展。

如果您仍然需要这样做,可以将插入(与删除不同)作为无锁操作执行到排序列表中,但要小心:

  1. 找到插入点,cur
  2. 创建新节点(将上一个/下一个链接分配给cur/cur->next
  3. 原子操作:compare_and_swap(cur->next, new, new->next);
    如果失败:if (new->value == next->value) return; // someone beat us to it
    否则:cur = cur->next 并重复舞蹈(列表已排序,有人插入我们之前)

即尝试链接一个新节点的结果要么是我们成功了,要么有人打败我们插入同一个节点(在这种情况下我们没问题 - 它已经在那里),或者有人插入了一个间隙(即现有的是NN+3,我们尝试了N+1,其他人成功了N+2)在这种情况下,我们重试直到我们成功或找到其他人完成的“我们的”节点。

同步删除要困难得多;为此查找 RCU(读取-复制-更新)。

【讨论】:

  • 这样定位插入点不会导致读者-作者问题吗?即,如果前面的列表正在修改,我们将无法搜索或找到插入点 curr。
  • 您正在测试“早于”,并且该点不会被插入更改(注意:我不是说 modification 因为那包括删除) .在“原子舞”中,如果另一个插入器与您比赛,您可能必须推进插入点,但您永远不需要后退。
  • @FrankH。我不明白为什么 compareAndSwap 有三个参数。在 Java 中是 (oldObject, newObject),这里的第三个参数是什么?
猜你喜欢
  • 1970-01-01
  • 2015-12-21
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 2020-06-13
相关资源
最近更新 更多