Naw*_*waz 17
这是说明范围锁定的小代码:
void do_something()
{
//here in the constructor of scoped_lock, the mutex is locked,
//and a reference to it is kept in the object `lock` for future use
scoped_lock lock(shared_mutex_obj);
//here goes the critical section code
}//<---here : the object `lock` goes out of scope
//that means, the destructor of scoped_lock will run.
//in the destructor, the mutex is unlocked.
Run Code Online (Sandbox Code Playgroud)
阅读评论.这解释了scoped_lock的工作原理.
这里scoped_lock通常是如何实现的(最小代码):
class scoped_lock : noncopyable
{
mutex_impl &_mtx; //keep ref to the mutex passed to the constructor
public:
scoped_lock(mutex_impl & mtx ) : _mtx(mtx)
{
_mtx.lock(); //lock the mutex in the constructor
}
~scoped_lock()
{
_mtx.unlock(); //unlock the mutex in the constructor
}
};
Run Code Online (Sandbox Code Playgroud)
Rei*_*ica 11
RAII(资源获取是初始化)的想法是创建一个对象并将其初始化连接成一个不可分割的动作.这通常意味着它们是在对象的构造函数中执行的.
嵌入式锁定通过在构造互锁时锁定互斥锁来工作,并在它们被破坏时解锁.C++规则保证当控制流离开作用域时(即使是异常),正在退出作用域本地的对象被正确销毁.这意味着使用范围锁而不是手动调用lock(),unlock()并且不可能意外地不解锁互斥锁,例如,当代码中间抛出异常时,lock()和unlock().
该原则适用于获取必须释放的资源的所有场景,而不仅仅是锁定互斥锁.为具有类似语法的其他操作提供此类"范围保护"类是一种很好的做法.
例如,我最近研究了一个数据结构类,它通常在修改时发送信号,但是对于某些批量操作必须禁用这些信号.提供范围保护类,在构造时禁用它们并在销毁时重新启用它们可防止对禁用/启用功能的潜在不平衡调用.
基本上它的工作原理是这样的:
template <class Lockable>
class lock{
public:
lock(Lockable & m) : mtx(m){
mtx.lock();
}
~lock(){
mtx.unlock();
}
private:
Lockable & mtx;
};
Run Code Online (Sandbox Code Playgroud)
如果你像这样使用它
int some_function_which_uses_mtx(){
lock<std::mutex> lock(mtx);
/* Work with a resource locked by mutex */
if( some_condition())
return 1;
if( some_other_condition())
return 1;
function_witch_might_throw();
return;
}
Run Code Online (Sandbox Code Playgroud)
您创建一个具有基于范围的生命周期的新对象。每当离开当前作用域并且该锁被销毁时,它都会自动调用mtx.unlock(). 请注意,在此特定示例中,互斥体上的锁是由lockRAIII 的构造函数获取的。
如果没有瞄准镜防护装置,您将如何做到这一点?每当您离开该功能时,您都需要调用mtx.unlock()。这 a) 很麻烦,b) 容易出错。此外,如果没有范围保护,您无法在返回后释放互斥体。
| 归档时间: |
|
| 查看次数: |
14765 次 |
| 最近记录: |