【问题标题】:std::scoped_lock or std::unique_lock or std::lock_guard?std::scoped_lock 或 std::unique_lock 或 std::lock_guard?
【发布时间】:2019-10-18 03:16:02
【问题描述】:

this 的问题我了解到std::scoped_lock 是“std::lock_guard 的严格高级版本”。

this 的问题中,我了解到“std::lock_guardstd::unique_lock 是相同的”,只是std::unique_lock 具有一些额外的功能(例如try_lock),但代价是一些额外的开销。

std::scoped_lockstd::unique_lock 相比如何?

我希望通过这个问题得到解答的一些相关问题。

  1. std::scoped_lockstd::unique_lock 有什么区别?
  2. 在什么情况下应该使用std::scoped_lock 而不是std::unique_lock
  3. 在什么情况下应该使用std::unique_lock 而不是std::scoped_lock
  4. 为什么std::scoped_lock 没有实现std::unique_lock 的一些附加功能?

【问题讨论】:

    标签: c++ multithreading c++11 locking c++17


    【解决方案1】:

    这两个对象用于不同的目的。 scoped_lock 用于希望以无死锁方式锁定一些互斥对象的简单情况。锁定单个互斥体只是锁定多个互斥体的一种特殊情况。对象是完全不动的,而且非常简单。

    unique_lock 提供了许多功能,其中很少有特别适用于同时锁定多个互斥锁的功能。

    • 延迟锁定。推迟必须是全部或全部;您要么推迟锁定所有互斥锁,要么不锁定它们。不清楚为什么要推迟锁定一系列互斥锁,因为如果其中任何一个锁失败,您将不得不放弃任何成功的锁。

    • 超时锁定。如果您想要 100 毫秒的超时时间,这是否意味着锁定所有互斥锁应该不超过 100 毫秒?即如果前3个立即锁,但下一个耗时75ms,如果第五个耗时30ms,是否应该认为超时?

    • 采用互斥锁。在单个操作中锁定多个互斥锁的全部意义在于能够避免死锁。这是通过以全局一致的顺序锁定互斥锁来完成的。也就是说,任何使用std::lock 等效调用锁定这些互斥对象的地方都会以相同的顺序锁定它们,无论如何。

      如果其中一个互斥锁已经被锁定(因此应该采用锁定),那么它被锁定在std::lock 之外,因此您无法保证它被锁定在全局一致的顺序中。这忽略了指定采用哪些互斥体以及锁定哪些互斥体的难度。

    • 所有权转让(可移动)。由于与采用锁类似的原因,这对于多个互斥锁来说是一个可疑的前景。仅当对std::lock 或等效项的单个调用锁定了所有感兴趣的互斥锁时,才能保证防止死锁。如果您要转移这些scoped_locks 的所有权,那么很容易在代码中处于同一范围内有多个scoped_locks 的位置,此时您可以一次锁定所有这些scoped_locks。这导致了std::lock 旨在避免的那种僵局。

    请注意,std::lockscoped_lock 功能的基础)甚至不会尝试提供任何这些功能。

    会不会有 scoped_lock 的专门化,它只采用一种提供 unique_lock 行为的互斥类型?当然。但这会违反scoped_lock 的目的,即作为多个互斥锁的死锁安全锁。它只是偶然废弃了lock_guard,因为它在单个互斥体的情况下具有相同的接口。

    此外,具有截然不同的接口和功能的模板专业化通常效果不佳。以vector<bool> 为例。

    【讨论】:

    • @lachy:如果某物可以移动,则称为“移动”。因此,如果某物不能移动,它就是“不动的”。
    • 我认为更标准的命名法是“可移动”,这是未来概念的名称:可移动,虽然移动/固定很可爱,但可能不太清楚。
    • 有什么理由更喜欢 scoped_lock 而不是 unique_lock?
    • @hddh:使用哪一个永远不是问题:如果您要锁定多个互斥锁,则使用scoped_lock;如果要锁定单个互斥体,请使用 unique_lock
    • fwiw,这个answer 很好地解释了为什么lock_guard 未被弃用
    猜你喜欢
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 2017-09-18
    • 2012-11-02
    • 2022-11-22
    • 1970-01-01
    相关资源
    最近更新 更多