std::lock_guard 还是 std::scoped_lock?

新手上路,请多包涵

C++17 引入了一个名为 std::scoped_lock 的新锁类。

从文档来看,它看起来类似于已经存在的 std::lock_guard 类。

有什么区别,我应该什么时候使用它?

原文由 Stephan Dollberg 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.3k
2 个回答

迟到的答案,主要是为了回应:

您可以考虑 std::lock_guard 已弃用。

对于需要恰好锁定一个互斥锁的常见情况, std::lock_guard 具有比 scoped_lock 更安全的 API。

例如:

 {
   std::scoped_lock lock;  // protect this block
   ...
}

上面的代码片段很可能是一个意外的运行时错误,因为它编译然后什么都不做。编码器可能的意思是:

 {
   std::scoped_lock lock{mut};  // protect this block
   ...
}

现在 它锁定/解锁 mut

如果在上面的两个示例中使用了 lock_guard ,则第一个示例是编译时错误而不是运行时错误,第二个示例具有与使用 scoped_lock 的版本相同的功能 --- .

所以我的建议是使用最简单的工具来完成这项工作:

  1. lock_guard 如果您需要在整个范围内准确锁定 1 个互斥锁。

  2. scoped_lock 如果您需要锁定多个不完全为 1 的互斥锁。

  3. unique_lock 如果您需要在块范围内解锁(包括与 condition_variable 一起使用)。

该建议 并不 意味着 应该重新设计 scoped_lock 以不接受 0 互斥锁。存在有效的用例,需要 scoped_lock 接受可能为空的可变参数模板参数包。空壳 不应 锁定任何东西。

这就是为什么 lock_guard 不被弃用的原因。 scoped_lock unique_lock 可能是 lock_guard 功能的超集,但事实是一把双刃剑。有时,类型 不会 做什么(在这种情况下为默认构造)同样重要。

原文由 Howard Hinnant 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是 C++ Concurrency in Action 的示例和引用:

 friend void swap(X& lhs, X& rhs)
{
    if (&lhs == & rhs)
        return;
    std::lock(lhs.m, rhs.m);
    std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock);
    std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock);
    swap(lhs.some_detail, rhs.some_detail);
}

对比

friend void swap(X& lhs, X& rhs)
{
    if (&lhs == &rhs)
        return;
    std::scoped_lock guard(lhs.m, rhs.m);
    swap(lhs.some_detail, rhs.some_detail);
}

std::scoped_lock 的存在意味着您在 c++17 之前使用 std::lock 的大多数情况现在可以使用 std::scoped_lock 编写,潜力较小对于错误,这只能是一件好事!

原文由 Chen Li 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题