std :: scoped_lock或std :: unique_lock或std :: lock_guard?

时间:2019-10-18 03:16:02

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

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的某些附加功能?

1 个答案:

答案 0 :(得分:4)

这两个对象有不同的用途。 scoped_lock仅用于希望以无死锁的方式锁定一定数量的互斥对象的简单情况。锁定单个互斥锁只是锁定多个互斥锁的一种特殊情况。该物体完全不动,非常简单。

unique_lock提供了许多功能,其中一些功能在同时锁定多个互斥锁时特别适用。

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

  • 超时锁定。如果您希望超时为100毫秒,是否意味着锁定所有互斥锁的时间不应超过100毫秒?也就是说,如果前三个立即锁定,而下一个锁定需要75毫秒,那么如果第五个锁定需要30毫秒,是否应该将其视为超时?

  • 采用互斥锁。在单个操作中锁定多个互斥锁的全部目的是为了避免死锁。这是通过按全局一致的顺序锁定互斥锁来完成的。也就是说,无论用什么方法std::lock锁定那些互斥对象的地方,无论如何都将以相同的顺序锁定它们。

    如果其中一个互斥锁已被锁定(因此应采用该锁定),则该互斥锁被锁定在std::lock之外,因此您不能保证它已按全局一致的顺序被锁定。这就忽略了指定采用哪种互斥锁和锁定哪些互斥锁的困难。

  • 所有权转移(可移动)。由于与采用锁类似的原因,这对于多个互斥锁是个可疑的前景。仅当一次调用std::lock或同等功能锁定所有感兴趣的互斥锁时,防止死锁的保证才起作用。如果要转移对这些scoped_lock的所有权,那么很容易在代码中的某个点上在同一范围内拥有多个scoped_lock,而可以锁定所有它们一气呵成。这可以避免std::lock产生的那种死锁。

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

是否会有scoped_lock的专门化,它仅采用一种提供unique_lock行为的互斥类型?当然。但这会违反scoped_lock的目的,该目的是为多个互斥对象提供一个死锁安全的锁定器。它只是偶然地淘汰了lock_guard,因为在单个互斥锁的情况下它具有相同的接口。

此外,拥有专门化的模板,它们的界面和功能差别很大,通常效果不佳。请以vector<bool>为例。