具有单个互斥锁的std :: scoped_lock行为

上下文:

我知道自std::lock_guard到来之后,std::scoped_lock就被弃用了。

我也知道std::scoped_lock是首选,因为它可以处理多个互斥量,并且使用死锁避免算法的方式与std::lock相同。

在这里,我对只有一个互斥锁的情况很感兴趣,因此我们不必担心避免死锁。

我从this answer读到:

您可以考虑弃用std::lock_guardstd::scoped_lock的单参数情况可以实现为专门化,因此您不必担心可能的性能问题。

问题:

我想知道这句话到底有多正确。

我的意思是,(通过标准)是否可以保证使用单个互斥锁std::scoped_lock是专用的,以消除由于避免死锁而造成的不必要的开销?


我的想法:

经过对该问题的调查,我从cppreference中发现了以下句子:

如果提供了多个互斥锁,则使用死锁避免算法,就像std::lock一样。

这可以让我们推断出否则不会发生这种情况(即,如果仅给出一个互斥锁)。
再次,这只是一个假设。

在这个c++ draft中,我没有看到关于这种专业化的任何明确提及。
我唯一的句子是:

sizeof...(MutexTypes)1时,提供的Mutex类型应满足 Cpp17BasicLockable 要求。否则,每种互斥锁类型均应满足 Cpp17Lockable 要求。

(重点是我的)

我知道 BasicLockable 要求强制要求lock()unlock()函数的存在,这些函数满足定义的here等条件。
另一方面, Lockable 要求假定为 BasicLockable 要求,并附加了一个try_lock()函数,该函数满足已定义的there等条件。

我知道要运行try_lock()使用的避免死锁算法,就需要std::lock函数。

根据上述草稿摘录中的内容,如果我们仅给try_lock()一个互斥量,则不需要std::scoped_lock函数。
这是否足以推断/考虑始终定义以上专业化(并且大概表现为std::lock_guard的行为)。
我会说是的,但是由于我从未见过任何明确提及,我想知道我是对的还是错过了什么?


编辑:

我刚刚注意到我错过了最重要的部分here,其中指出:

效果:用pm初始化tie(m...)。然后,如果sizeof...(MutexTypes)0,则没有效果。否则,如果sizeof...(MutexTypes)1,则m.lock()否则,lock(m...)

(重点是我的)

回答我的询问时,std::lock仅在给定的互斥量不止一个时被调用。我应该在问这个问题之前就看过它。

crediblebridge 回答:具有单个互斥锁的std :: scoped_lock行为

仅提供一个互斥锁时,要求

std::scoped_lock的行为与std::lock_guard相同。因此,对于单个互斥锁情况有不同的要求。

这可以通过专门化来完成,也可以通过不同的内部机制来完成,只要行为相同即可。

,

如果您阅读了lock_guard的规范(位于scoped_lock的正上方),则应该清楚。

[thread.lock.guard]-3

用m初始化pm。调用m.lock()

[thread.lock.scoped]-3

使用tie(m ...)初始化pm。 [...]否则,如果sizeof ...(MutexTypes)为1,则m.lock()。 [...]

它没有明确提到要使用lock_guard,但必须具有相同的行为。

,

通过专业化,该标准很少会保证某种优化(值得注意的例子是不同迭代器类型a和可憎性std::vector<bool>的专业化)。为此,有两种方法可以解决:

  1. 信任您的编译器/标准库的实现。编译器是史诗级的,它们可以进行极其高级的优化,其中有些是您梦dream以求的。在大多数情况下,STL的实现都很棒。在某些情况下它们的速度较慢,因为它们必须能够处理奇怪的边缘情况,但是这里已经有了另一种特殊化,因为一个参数情况仅需要BasicLockable,因此它将具有不需要的实现try_lock,为什么不那么有效。
  2. 执行您的代码。测试它是否足够快,测试scoped_lock是否在代码的热路径上,以及您是否真的认为(并有数据证明)scoped_lock很慢,然后才替换它lock_guard并再次测试。
本文链接:https://www.f2er.com/2691953.html

大家都在问