是否将 unique_lock 用于可以由 lock_guard 完成的任务较慢?

Posted

技术标签:

【中文标题】是否将 unique_lock 用于可以由 lock_guard 完成的任务较慢?【英文标题】:Is using unique_lock for a task that can be acomplished by lock_guard slower? 【发布时间】:2013-10-24 16:52:20 【问题描述】:

我对@9​​87654321@ 存在的原因感到困惑。是吗:

    unique_lock更简单的界面? 比unique_lock性能更好? 还有别的吗?

【问题讨论】:

【参考方案1】:

lock_guard 可以用一个状态单元来实现:一个指针或对它已锁定的Mutex 类型的引用。

unique_lock 必须保持该状态,并且知道当前是否已锁定,因为unique_lock 可以有一个未锁定的Mutex。这意味着它必须至少有一个 bool 的额外状态。

lock_guard 在获取和释放Mutex 时提供了一个 开销的 RAII 锁定/解锁包装器。基本上,lock_guard 意味着避免使用 RAII 处理 Mutex 上的锁的理由为零。

unique_lock 只能达到零开销,前提是编译器可以确信您仅以可以使用 lock_guard 的方式使用它(即,构造它,然后销毁它,而不是摆弄它)。

除了这些效率参数之外,看到lock_guard程序员知道它会持续到作用域结束,而无需检查作用域中的代码。看到unique_lock 的程序员必须检查变量的所有使用以了解是否是这种情况。

但以上只是一半的原因。

另一半是因为 C++11 的大部分线程库是基于 boost 库的,它已经实现了一个大部分独立于平台的线程库。 Boost 同时具有lock_guardunique_lock,其语义与C++11 版本几乎相同。

所以当boost线程库被标准化时,无论是在哪里都被带入了,并且没有人消除它们。

【讨论】:

【参考方案2】:

您几乎在这里回答了自己的问题 - 1) 和 2) 都是很好的理由。 std::lock_guard 是一个简单的作用域锁定对象。互斥体获取超时等特性增加了互斥体原语的复杂性,增加了执行操作所需的时间和互斥体争用的可能性。那么为什么要为不需要的东西买单呢?

带有或不带有超时的“try_locking”是否是好的设计是另一个问题;比如线程取消,一个 C++11 没有实现的破碎设计。

【讨论】:

以上是关于是否将 unique_lock 用于可以由 lock_guard 完成的任务较慢?的主要内容,如果未能解决你的问题,请参考以下文章

关于使用 std::unique_lock 的说明

为啥 std::condition_variable 采用 unique_lock 而不是 lock_guard? [复制]

使用std::lock 和 std::unique_lock来起先swap操作

第一次锁定和创建 lock_guard(adopt_lock) 和创建 unique_lock(defer_lock) 和锁定有啥区别?

VIVADO的XDC怎么实现LOC约束

std::unique_lock 移动语义