作用域锁定是如何工作的
How does scope-locking work?
我正在学习c++,我看到作用域锁的源代码非常简单。它是如何工作的,这是"资源获取即实例化"(RAII)的一个例子吗?
下面是一小段代码来说明作用域锁:
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.
阅读评论。这就解释了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
}
};
RAII(资源获取即初始化)的思想是将创建对象和初始化对象连接在一起,形成一个不可分离的动作。这通常意味着它们在对象的构造函数中执行。
作用域锁的工作原理是:在互斥锁被构造时锁定它,在互斥锁被销毁时解锁它。c++规则保证当控制流离开一个作用域时(即使是通过异常),被退出的作用域的局部对象将被正确地销毁。这意味着使用作用域锁而不是手动调用lock()
和unlock()
,不可能意外地不解锁互斥锁,例如,当在lock()
和unlock()
之间的代码中间抛出异常时。
这个原则适用于所有获取必须释放的资源的场景,而不仅仅是锁定互斥锁。为其他具有类似语法的操作提供这样的"作用域保护"类是一个很好的实践。
例如,我最近研究了一个数据结构类,当它被修改时通常会发送信号,但是对于一些批量操作必须禁用这些信号。提供一个作用域保护类,在构造时禁用它们,在销毁时重新启用它们,可以防止对disable/enable函数的潜在不平衡调用。
基本上是这样的:
template <class Lockable>
class lock{
public:
lock(Lockable & m) : mtx(m){
mtx.lock();
}
~lock(){
mtx.unlock();
}
private:
Lockable & mtx;
};
如果你用
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;
}
创建一个具有基于作用域生存期的新对象。无论何时,只要当前作用域仍然存在并且这个锁被销毁,它就会自动调用mtx.unlock()
。注意,在这个特殊的例子中,互斥锁是由lock
的构造函数获得的,也就是RAIII。
如果没有瞄准镜保护装置,你会怎么做?无论何时离开该函数,都需要调用mtx.unlock()
。这是a)繁琐和b)容易出错的。如果没有作用域保护,也不能在返回后释放互斥锁。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?
- sdl软件渲染器不工作,工作在硬件加速的一个