范围锁定如何工作?

时间:2013-01-11 10:48:19

标签: c++

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

3 个答案:

答案 0 :(得分:16)

以下是说明范围锁定的小代码:

 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
      }
};

答案 1 :(得分:10)

RAII(资源获取是初始化)的想法是创建一个对象并将其初始化连接成一个不可分割的动作。这通常意味着它们是在对象的构造函数中执行的。

Scoped锁通过在构造互锁时锁定互斥锁来工作,并在它们被破坏时解锁。 C ++规则保证当控制流离开作用域时(即使是异常),正在退出作用域本地的对象被正确销毁。这意味着使用范围锁而不是手动调用lock()unlock()使得无法意外地解锁互斥锁,例如在lock()unlock()之间的代码中间抛出异常时。

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

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

答案 2 :(得分:3)

基本上它的工作原理如下:

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