Answers:
的scoped_lock
是一个严格的优越版本lock_guard
用于锁定互斥所有的一次任意数量(使用相同的死锁避免算法如std::lock
)。在新代码中,您只能使用scoped_lock
。
lock_guard
仍然存在的唯一原因是兼容性。它不能被删除,因为它在当前代码中使用。此外,事实证明,不希望更改其定义(从一元更改为可变),因为这也是可观察的,因此是重大更改(但出于某种技术原因)。
lock_guard
。但这肯定会使后卫类易于使用。
唯一且重要的区别是,std::scoped_lock
一个可变参数构造函数使用多个互斥量。这允许以死锁的方式锁定多个互斥锁,从而避免了仿佛std::lock
使用过的方式。
{
// safely locked as if using std::lock
std::scoped_lock<std::mutex, std::mutex> lock(mutex1, mutex2);
}
以前,你必须做一个小舞用安全的方式来锁定多个互斥std::lock
为解释这个答案。
范围锁的添加使其更易于使用并避免了相关错误。您可以考虑std::lock_guard
弃用。单论证案例std::scoped_lock
可以实现为专门化,这样您不必担心可能的性能问题。
GCC 7已经支持std::scoped_lock
由此可以看出这里。
有关更多信息,您可能需要阅读标准论文
scoped_lock lk; // locks all mutexes in scope
。LGTM。
scoped_lock lk;
是的新缩写scoped_lock<> lk;
。这里是没有互斥。所以你是对的。;-)
答案较晚,主要是针对以下问题:
您可以考虑
std::lock_guard
弃用。
对于通常需要精确锁定一个互斥锁的常见情况,std::lock_guard
其API的使用要比稍微安全一些scoped_lock
。
例如:
{
std::scoped_lock lock; // protect this block
...
}
上面的代码片段很可能是偶然的运行时错误,因为它会编译然后完全不执行任何操作。编码器可能意味着:
{
std::scoped_lock lock{mut}; // protect this block
...
}
现在它会锁定/解锁mut
。
如果lock_guard
在上面的两个示例中使用,则第一个示例是编译时错误,而不是运行时错误,第二个示例与使用的版本具有相同的功能scoped_lock
。
因此,我的建议是使用最简单的工具来完成这项工作:
lock_guard
如果您需要为整个示波器精确锁定1个互斥锁。
scoped_lock
如果您需要锁定多个互斥量不完全为1。
unique_lock
如果您需要在区块范围内解锁(包括使用condition_variable
)。
这个建议并 没有暗示scoped_lock
要重新设计,以不接受0互斥。在有效的使用案例中,需要scoped_lock
接受可变参数模板参数包(可能为空)。而空的情况下,应不作任何锁定。
这就是为什么lock_guard
不推荐使用。 scoped_lock
并且 unique_lock
可能是的功能超集lock_guard
,但事实是一把双刃剑。有时,类型将不起作用也同样重要(在这种情况下为默认构造)。
这是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
意味着std::lock
现在可以使用编写大多数在c ++ 17之前使用过的情况std::scoped_lock
,而发生错误的可能性较小,这只是一件好事!