范围锁定如何工作?

Jas*_*ues 8 c++

我正在学习C++,我发现范围锁的源代码非常简单..它是如何工作的,这是"资源获取是实例化"(RAII)的一个例子?

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().

该原则适用于获取必须释放的资源的所有场景,而不仅仅是锁定互斥锁.为具有类似语法的其他操作提供此类"范围保护"类是一种很好的做法.

例如,我最近研究了一个数据结构类,它通常在修改时发送信号,但是对于某些批量操作必须禁用这些信号.提供范围保护类,在构造时禁用它们并在销毁时重新启用它们可防止对禁用/启用功能的潜在不平衡调用.


Zet*_*eta 5

基本上它的工作原理是这样的:

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) 容易出错。此外,如果没有范围保护,您无法在返回后释放互斥体。