我最近尝试使用跳过列表数据结构实现并发优先级队列 - 为了这个问题,如果你不知道跳过列表是什么,我相信只是想象链接列表会足以回答。我尝试了最小的锁定(即同时允许多个队列和队列,只在必要时锁定节点或其前向指针,尽快释放锁定,使用Interlocked's遍历列表等)。
我对结果很满意。但是,编写一个带有由同步锁定包围的添加和删除的常规跳转列表(即在任何给定时间只允许一次操作),实际上是两倍快。
我认为我的实施必须有bug。但是,即使是Microsoft网站上列出的“并发优先级队列”,实际上也只允许一次进行一次操作(即同步锁定排队和出队)
作为一般规则,(并且如果这个问题过于笼统,请原谅我),更精细的锁定在什么时候实际上会导致性能提升?我想在我的情况下,因为我实际上必须使用Interlocked.Exchange遍历大型列表(有更好的方法吗?)以及多个测试和测试以及集合等,这会减慢排队和出队的速度。
此外,是否有工具可以帮助我确定大部分时间花在哪里?感谢。
答案 0 :(得分:3)
持续检查锁定区域当前是否空闲,设置锁定,然后在离开时释放它是一种开销。实际上,如果您实际上很少与其他任何人竞争访问该关键部分,那么您只是在没有任何理由的情况下执行了此开销。另一方面,如果有许多线程试图使用您的数据结构,那么您可能会发现并行运行操作(如果您有许多核心CPU)的性能提升超过了管理锁的开销。
对于这些类型的数据结构,有几十个线程同时尝试使用数据结构,同时执行通常不需要它们彼此等待的操作,这是一种相当罕见的情况。因此,简而言之,您可能会生成测试用例,通过添加线程并正确管理他们正在执行的操作,导致较小的锁定案例表现更好。如果您当前的测试是您实际计划如何使用数据结构的合理表示,那么显然您的使用将无法从更精细的锁定方案中受益。
答案 1 :(得分:1)
您同步的次数越多,您的应用程序将遭受性能损失。 使用syncroot可能导致问题不是复杂情况下的方法。
诀窍是在同步中找到合适的平衡点;足以让它变得可靠,例如没有竞赛条件。
查看System.Collections.Concurrent命名空间