C++ 在新范围中使用unique_lock是否等同于在共享资源的工作结束时解锁调用?
当开发者在自动解锁互斥锁的新范围中使用C++ 在新范围中使用unique_lock是否等同于在共享资源的工作结束时解锁调用?,c++,multithreading,c++11,C++,Multithreading,C++11,当开发者在自动解锁互斥锁的新范围中使用std::unique_lock时,我看到了很多代码示例: ... // do some staff { std::unique_lock<std::mutex> lock(shared_resource_mutex); // do some actions with shared resource } // do some staff ... 这两段代码是等价的吗?开发人员使用第一个变体的目的是什么?也许要强调(使用括号)不能并行执行
std::unique_lock
时,我看到了很多代码示例:
...
// do some staff
{
std::unique_lock<std::mutex> lock(shared_resource_mutex);
// do some actions with shared resource
}
// do some staff
...
这两段代码是等价的吗?开发人员使用第一个变体的目的是什么?也许要强调(使用括号)不能并行执行的代码 当对象在作用域末尾被销毁时,锁被释放。这就是RAII的全部要点 使用RAII的好处是,您不能忘记解锁,无论您如何离开范围。例如,如果抛出异常,锁仍将被释放
如果您只需要在构造时锁定,在销毁时解锁,那么就可以使用更简单/更合适的类。我认为前一种方法更安全、更一致、更易于阅读
<强>首先考虑安全性:< /强>
void function()
{
std::unique_lock<std::shared_mutex> lock(mtx);
// exclusive lock stuff
lock.unlock();
// std::shared_lock<std::shared_mutex> lock(mtx); // whoops name in use
std::shared_lock<std::shared_mutex> lock2(mtx);
// read only shared lock stuff here
lock2.unlock(); // what if I forget to do this?
lock.lock(); // if I forgot to call lock2.unlock() undefined behavior
// back to the exclusive stuff
lock.unlock();
}
这两种方法都是正确的,您可以根据具体情况选择其中一种。例如,当使用条件变量/锁组合时,能够显式锁定和解锁锁通常很有用 我发现另一种方法既有表现力又安全:
#include <mutex>
template<class Mutex, class Function>
decltype(auto) with_lock(Mutex& m, Function&& f)
{
std::lock_guard<Mutex> lock(m);
return f();
}
std::mutex shared_resource_mutex;
void something()
{
with_lock(shared_resource_mutex, [&]
{
// some actions
});
// some other actions
}
#包括
模板
decltype(自动)带锁(互斥锁和m、函数和f)
{
标准:锁和防护锁(m);
返回f();
}
std::互斥体共享资源互斥体;
使某物无效
{
带锁(共享资源互斥,[&]
{
//一些行动
});
//其他一些行动
}
“例如,如果抛出异常,锁仍将被释放。”但对于另一个变体也是如此。是的,我知道RAII,但我说的是另一件事。unique_lock有一个unlock方法,可以尽早(在可能的情况下)释放资源上的锁,以改进并行化,即使在unlock之前抛出异常,一切都会正常。询问人们为什么使用{}来执行此操作而不是解锁调用。是的,但在这种情况下,您将有两种不同的方式来释放锁,而不是仅使用一种。现在,初学者可能看不到互斥锁是在哪里发布的。同时调用unlock,初学者可能会认为锁不会在抛出时释放。引入新的作用域通常是可能创建子函数的标志。。。
void function()
{
{
std::unique_lock<std::shared_mutex> lock(mtx);
// exclusive lock stuff
}
{
std::shared_lock<std::shared_mutex> lock(mtx);
// read only shared lock stuff here
}
{
std::unique_lock<std::shared_mutex> lock(mtx);
// back to the exclusive stuff
}
}
#include <mutex>
template<class Mutex, class Function>
decltype(auto) with_lock(Mutex& m, Function&& f)
{
std::lock_guard<Mutex> lock(m);
return f();
}
std::mutex shared_resource_mutex;
void something()
{
with_lock(shared_resource_mutex, [&]
{
// some actions
});
// some other actions
}