【问题标题】:std::scoped_lock and mutex orderingstd::scoped_lock 和互斥量排序
【发布时间】:2021-11-20 22:44:06
【问题描述】:

我正在尝试确定std::scoped_lock 是否尝试建立排序或互斥ID 以按照规定的顺序获取锁。我不清楚它是通过对browsable implementation I found googling around 的简要介绍来实现的。

如果不这样做,什么是最接近获取有序锁集的标准实现?

通常,避免死锁最简洁的方法是始终以相同的顺序获取一组锁(是的,当然,总是在尝试再次获取新锁之前将它们全部释放,但也许 2PL 有点超出了std::scoped_lock 的目标应该是什么)

【问题讨论】:

    标签: c++ concurrency c++17 locking deadlock


    【解决方案1】:

    std::lock 的顺序直到运行时才定义,也不是固定的。它是通过算法对std::lock 的每个单独调用通过实验发现的。对std::lock 的第二次调用可能会以与第一次不同的顺序锁定互斥锁,即使两个调用可能在调用站点以相同的顺序使用相同的互斥锁列表。

    这里是std::lock的几种可能实现的详细性能分析:http://howardhinnant.github.io/dining_philosophers.html

    使用固定的互斥顺序是上述链接中性能比较的算法之一。对于所进行的实验,它并不是性能最好的算法。

    OP 指向的libstdc++ implementationthe analysis 标记为“聪明和礼貌”的高质量实现

    【讨论】:

    • 我很想做一个不同的测试,我相信有序策略应该赢(或至少不会显着输),在更分散的锁分布下(情况就是这样,比方说,索引或表的基于范围的锁定),并且对一小部分低级锁定的考虑较少。如果我这样做了,我会在你的博客上 ping 你
    • 谢谢!是的,我怀疑你是对的,这样的实验将显示算法之间的差异要小得多。该分析旨在突出算法之间的差异。 问题描述部分包含以下引用:“如果场景是低争用的,那么算法无关紧要,只要它避免死锁。”
    • 我对这些例子有点困惑。所以unique_lock 应该在析构函数中释放,但是为什么你在标准普尔::lock 上明确调用release 1 日unique_lock?还有为什么需要在有序的::lock 中显式调用它们?这有关系吗?
    • u0.release() 之前,l0 引用的互斥锁由参数l0 和本地unique_locku0 拥有。 u0.release() 在算法成功返回之前将唯一所有权转移给 l0。如果l1.try_lock() 会导致异常,那么当异常传播出去时,本地u0 的销毁将解锁l0,从而使所有互斥锁解锁。
    • 换句话说,本地的unique_locks 只不过是用于异常安全的标准 RAII 设备。如果没有抛出异常,那么它们将释放其所有权,将按引用参数列表作为唯一所有者。
    【解决方案2】:

    scoped_lock 的构造函数被声明为在其互斥体上调用std::lock,因此其行为受此函数控制。和std::lock is specifically defined 以避免在它锁定的内容上出现死锁。它锁定互斥锁的顺序是未定义的,但不会导致死锁。

    【讨论】:

    • 你是说互斥顺序是 1) 未定义但在编译时固定 2) 它在运行时未定义但在进程的生命周期内固定或 3) 它甚至避免死锁何时以不同的顺序获取锁?
    • 未定义,但不会导致死锁。而已。实现的具体实现方式取决于实现。但由于lock 不是constexpr,因此无法在编译时修复任何内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多