并发链表

时间:2010-11-12 17:58:25

标签: c++ multithreading pthreads

我正在尝试在c ++中设计一个允许并发访问的链表。显然,对于该列表使用单个锁是非常低效的,因为可以并行更新不相交的区域。现在除了每个节点存储一个锁之外,还有什么选择?

另外,在这种情况下,非阻塞版本会更好吗?任何相关链接,任何人?

编辑:感谢您的回复。我想补充一些事情:

  1. 如何为每个M节点存储N个锁,而不是1:1锁:节点比?有些线程会等待,但这是一种权衡。你觉得怎么样?
  2. 如果我打算在此链表中找到一些节点,则看起来需要锁定所有互斥锁。这是一个问题,因为锁定和解锁所有互斥锁都很耗时。有没有人有更好的选择?
  3. 我对非阻塞算法持开放态度。但是如何在不使用汇编的情况下在旧的C ++中使用CAS?我听说gcc有一些__sync属性做类似的工作,但不确定。
  4. 使用非阻止方法,如何在链表上进行查找?

5 个答案:

答案 0 :(得分:4)

可以使用互锁函数实现非阻塞单链表:

Interlocked Singly Linked Lists

我认为没有互锁的比较和交换(CAS)可以实现一个非阻塞的双向链表,而CAS并不广泛。

答案 1 :(得分:2)

Linked lists are inherently sequential data structures.无论您使用何种机制来实现它,接口和预期行为都意味着顺序逻辑。

你想做什么?这应该决定您使用的数据结构,而不是您熟悉的数据结构的熟悉程度。

答案 2 :(得分:1)

根据您将如何使用该列表,您可以采用多种不同的方式。

首先,对于列表,单个互斥锁不一定是大问题,因为列表可以支持拼接。假设您有一个字符AF列表和另一个列表BCDE。您不必锁定互斥锁,插入B,再次锁定它,插入C等。您可以通过将A的下一个指针设置为B而将E的下一个指针设置为F,从而在A和F之间一次性插入BCDE,从而形成ABCDEF。无论您想要一次插入多少元素,您只需要一个锁。即使对于双重链表也是如此。因此,它可能不是您应用程序中的瓶颈。

假设它会成为瓶颈,你需要考虑你是否会有一个或多个作家以及一个或多个读者。

假设您有一个编写器和多个读取器,您可以完全通过使用原子指令来避免互斥锁,假设它们可用于您的体系结构。在GCC中,这些可以通过内置的__sync_ *函数获得,在Visual C ++中它们可以通过Interlocked *获得,但如果您遇到缺乏对它们的直接支持的编译器,您仍然可以通过内联汇编使用它们。编写器将使用原子指令以原子方式设置列表中的补丁元素的下一个指针。

希望这能让你开始。为了得到一个深刻的答案,我建议提出另一个问题,包括:

  1. 是否有一个/多个读者?
  2. 是否有一个/多个作家?
  3. 单链或双链表?
  4. 了解您的用例是什么。

答案 3 :(得分:0)

你确定这是一个值得解决的问题吗?将实际最终用法封装到处理普通list锁定的类中并提供线程安全接口可能更有用吗?这样你就不会试图把锁定放在一个太低的水平上(正如你猜测的那样,这不是一个容易解决的问题)。

答案 4 :(得分:0)

跳过列表怎么样?看看“并发”包中的java实现。