std::scoped_lock or std::unique_lock or std::lock_guard?

std::scoped_lock or std::unique_lock or std::lock_guard?

本文关键字:std lock or guard unique scoped      更新时间:2023-10-16

从这个问题中,我了解到std::scoped_lock是"std::lock_guard的严格高级版本"。

从这个问题中,我了解到"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的一些附加功能?

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

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

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

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

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

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

  • 所有权转让(可移动(。对于多个互斥锁来说,这是一个可疑的前景,原因与采用锁类似。仅当对std::lock或等效项的单个调用锁定所有相关互斥锁时,针对死锁的保证才有效。如果您要移动这些scoped_lock的所有权,则很容易在代码中在同一范围内有多个scoped_lock,而此时您可以一次性锁定所有这些。这恰恰是std::lock为了避免的那种僵局。

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

是否存在一种只采用一种提供unique_lock行为的互斥锁类型的scoped_lock专业化?确定。但这违反了scoped_lock的目的,即成为多个互斥锁的死锁安全储物柜。它只是偶然地lock_guard过时了,因为它在单个互斥锁的情况下具有相同的接口。

此外,具有截然不同的界面和功能的模板专用化通常效果不佳。请参阅vector<bool>作为示例。