1

我最近尝试使用跳过列表数据结构实现并发优先级队列——为了这个问题,如果你不知道什么是跳过列表,我相信只画一个链表就足够了回答。我尝试了最小锁定(即同时允许多个入队和出队,仅在必要时锁定节点或其前向指针,尽快释放锁,使用互锁遍历列表等)。

我对结果很满意。然而,编写一个带有同步根锁的添加和删除的常规跳过列表(即在任何给定时间只允许一个操作),实际上速度是原来的两倍。

我认为我的实现中一定有错误。但是,即使是 Microsoft 网站上列出的“并发优先级队列”,实际上也一次只允许一个操作(即围绕入队和出队的同步根锁定)

http://code.msdn.microsoft.com/Samples-for-Parallel-b4b76364/sourcecode?fileId=44488&pathId=1696822056

作为一般规则(如果这个问题过于笼统,请原谅我),在什么时候更细粒度的锁定实际上会导致性能提升?我想在我的情况下,因为我实际上必须使用 Interlocked.Exchange 遍历大型列表(有更好的方法吗?)以及多个测试和测试和设置等,这会减慢入队和出队的速度。

此外,是否有工具可以帮助我确定大部分时间都花在了哪里?谢谢。

4

2 回答 2

3

不断检查锁定区域当前是否空闲,设置锁定,然后在离开时释放它会产生开销。如果在实践中,您很少与其他人竞争访问该关键部分,那么您只是无缘无故地执行了该开销。另一方面,如果有大量线程试图使用您的数据结构,那么您可能会发现并行运行操作(如果您有多个核心 CPU)所提高的性能超过了管理锁的开销。

对于这些类型的数据结构,有几十个线程同时尝试使用该数据结构,同时执行通常不需要它们相互等待的操作,这是一种相当罕见的情况。因此,简而言之,您可能会生成测试用例,通过添加线程并正确管理它们都在做什么,从而使较小的锁定用例表现得更好。如果您当前的测试是您实际计划如何使用数据结构的合理表示,那么显然您的使用不会从更复杂的锁定方案中受益。

于 2012-10-19T14:18:50.187 回答
1

您同步的越多,您的应用程序遭受的性能损失就越多。使用 syncroot 可能会导致问题,这不是在复杂情况下的方法。

诀窍是在同步中找到正确的平衡;足以让它可靠,例如没有竞争条件。

看看 System.Collections.Concurrent 命名空间

于 2012-10-19T14:09:40.100 回答