2013-01-11 4 views
7

私はC++を学んでいます。スコープロックのソースコードはかなりシンプルです。 。それはどのように機能し、これは「リソース獲得はインスタンス化ですか」(RAII)の例ですか?ここでスコープロックはどのように機能しますか?

+2

:http://stackoverflow.com/questions/10095185/why-is-raii-so-named/10095468#10095468 – RedX

答えて

10

RAII(リソース取得された初期化)の考え方は、オブジェクトを作成し、それを初期化すると、1つの分離不可能な行動に接合されているということです。これは一般に、オブジェクトのコンストラクタで実行されることを意味します。

スコープロックは、作成時にミューテックスをロックし、破壊されたときにロックを解除することで機能します。 C++の規則は、制御フローが(例外を介して)スコープから離れるときに、終了するスコープのローカルのオブジェクトが正しく破棄されることを保証します。つまり、lock()unlock()を手動で呼び出す代わりにスコープロックを使用すると、誤ってミューテックスをロック解除できなくなります。コードの中間でlock()unlock()の間に例外がスローされたとき。

この原則は、ミューテックスをロックするだけでなく、解放する必要があるリソースを取得するすべてのシナリオに適用されます。類似の構文を持つ他の操作にこのような「スコープガード」クラスを提供することは良い習慣です。

例えば、私は最近、通常はシグナルが変更されたときにシグナルを送信するデータ構造クラスに取り組んだが、一部のバルク操作ではこれらを無効にする必要があります。構築時にそれらを無効にし、破棄時にそれらを再び有効にするスコープガードクラスを提供することにより、ディスエーブル/イネーブル機能への不均衡なコールの可能性を防ぎます。

15

は、スコープのロックを示して少しコードです:

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

これは素晴らしい答えですが、私は彼ので@Angewを受け入れていますRAIIについての私の質問の第二の部分にも対処しました。 –

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()が呼び出されます。この特定の例では、mutexのロックは、RAIIIであるlockのコンストラクタによって取得されることに注意してください。

あなたはどのようにスコープガードなしでこれを行いますか?この機能を離れるときはいつでもmtx.unlock()に電話する必要があります。これはa)煩雑でb)エラーを起こしやすい。また、スコープガードなしでの後にmutex をリリースすることはできません。 RAIIの命名については

関連する問題