【问题标题】:When is more granular locking better for performance?什么时候更细粒度的锁定对性能更好?
【发布时间】:2012-10-19 22:18:50
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

    标签: c# multithreading .net-4.0 locking


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      技巧是在同步中找到合适的平衡;足以让它可靠,例如没有竞争条件。

      查看 System.Collections.Concurrent 命名空间

      【讨论】:

        猜你喜欢
        • 2012-02-20
        • 2013-09-27
        • 2011-05-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多