【问题标题】:Concurrent skiplist Read locking并发跳过列表读取锁定
【发布时间】:2012-10-02 16:05:29
【问题描述】:

我会尽量让这个问题尽可能笼统,但我会简单介绍一下我的实际问题——

我正在尝试为优先级队列实现并发跳过列表。每个“节点”都有一个值和一个“前向”节点数组,其中 node.forward[i] 表示跳过列表第 i 级上的下一个节点。对于写访问(即插入和删除),我使用自旋锁(仍在确定这是否是最好的锁)

我的问题本质上是,当我需要读取访问权限以进行遍历时,

node = node.forward[i]

围绕这样的事情我需要什么样的线程安全?如果另一个线程在我读取的同时修改 node.forward[i](没有当前的读取锁定机制),这里会发生什么?

我最初的想法是在 Forward 索引器的 getter 和 setter 上设置一个 ReaderWriterLockSLim。在这种情况下会不会有太多不必要的锁定?

编辑:或者最好改为使用 Interlocked.Exchange 来进行我所有的读取?

【问题讨论】:

  • +1 因为跳过列表很棒。 :D

标签: c# multithreading algorithm .net-4.0


【解决方案1】:

如果另一个线程在我读取的同时修改 node.forward[i](没有当前的读取锁定机制),这里会发生什么?

这真的取决于实施。在设置“forward”时可以使用Interlocked.Exchange,以防止引用无效(因为它可以使“set”原子化),但不能保证您会阅读哪个引用。但是,如果使用幼稚的实现,任何事情都可能发生,包括获取不良数据。

我最初的想法是在 Forward 索引器的 getter 和 setter 上设置一个 ReaderWriterLockSLim。

这可能是一个很好的起点。使用ReaderWriterLockSlim 制作正确同步的集合相当容易,并且功能始终是第一要务。

这可能是一个很好的起点。

在这种情况下会不会有太多不必要的锁定?

如果不看看你是如何实现它的,就无法知道它是如何实现的,更重要的是,它是如何被使用的。根据您的使用情况,您可以如有必要在此时分析和寻找优化机会。

附带说明 - 您可能需要重新考虑使用node.Forward[i],而不是这里更多的“链接列表”方法。对Forward[i] 的任何访问都可能需要相当多的同步来遍历跳过列表i 步骤,如果在nodei 之间的任何地方存在并发写入,所有这些都需要一些同步以防止错误node 之外的元素。如果您只向前看一步,则可以(可能)减少所需的同步量。

【讨论】:

  • node.Forward[3] 并不表示“此节点之后的节点 3 节点”,它表示跳过列表第 3 层上的下一个节点。我认为这是实现跳过列表的一种相当标准的方法,无论是否并发。感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
相关资源
最近更新 更多