2013-07-18 26 views
5

シンプルな質問 - 基本的に、私はミューテックスのロックを解除する必要がありますか?または単にスコープ演算子を使うことができますか?ミューテックスは自動的にロック解除されますか?ミューテックスが有効範囲外になるとロックが解除されますか?

すなわち:

{ 
    pthread_mutex_lock (&myMutex); 
    sharedResource++; 
} // my mutex is now unlocked? 

またはべきI:RAIIスコープ方式を使用して

{ 
    pthread_mutex_lock (&myMutex); 
    sharedResource++; 
    pthread_mutex_unlock (&myMutex); 
} 
+5

どのmutex実装を使用していますか?あなたがmutexの実装でRAIIをサポートしていない限り、明示的にmutexのロックを解除する必要があります。 – Void

+0

ありがとう@Void。私はpthread.hを使用しています。つまり、pthread_mutex_unlock()とpthread_mutex_lock()です。 RAIIとは何ですか? –

+3

@AmitNayar:http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initializationを参照してください。C++ではおそらくメモリやその他の動的リソースを正しく管理することが不可能なので、おそらくC++の最も重要なイディオムです。 –

答えて

16

あなたの例では、ミューテックスが範囲外になることはありません。特定の関数がスコープの最後で呼び出しを必要としていることをコンパイラが知る方法はないので、最初の例はではなく、はmutexのロックを解除します。

(エラーが発生しやすい)関数を使用してミューテックスをロックおよびロック解除する場合は、保護された操作が例外をスローした場合でも常にunlock()を呼び出す必要があります。

これを行うための最善の方法は、あなたが使用後に解放する必要のある他のリソースの場合と同じように、ロックを管理するためにRAIIクラスを使用することです:現代のC++では

class lock_guard { 
public: 
    explicit lock_guard(mutex & m) : m(m) {mutex_lock(m);} 
    ~lock_guard() {mutex_unlock(m);} 

    lock_guard(lock_guard const &) = delete; 
    void operator=(lock_guard &) = delete; 

private: 
    mutex & m; 
}; 

// Usage 
{ 
    lock_guard lock(myMutex); 
    shared_resource++; 
} // mutex is unlocked here (even if an exception was thrown) 

ためstd::lock_guardstd::unique_lockを使用し、この。

2

それはmutexが常に早期例外またはに直面しても、ロックが解除されることを保証するのではるかに優れています戻る。

あなたはインクリメントし、それをロックする必要はありません、その場合には代わりにstd::atomic<int>を使用して検討するかもしれないけれども、あなたがC++ 11へのアクセスを持っている場合。

2

この場合、このコードが有効範囲外になると、mutexはロックされません。 RAIIは非ヒープ割り当てられたオブジェクトがスコープの外に出る時にデストラクタが自動的に呼び出されているという事実を使用して、次の

ミューテックスロッカー。その後、mutexをロックしたオブジェクトがスコープから外れると、mutexはロック解除されます。コードの場合、中括弧のスコープ内にオブジェクトが割り当てられないため、スコープが終了するとロックアウトされる可能性はありません。 QtライブラリからQMutexLockerを使用して例えば

、あなたはスコープが終了したときに、ミューテックスのロックが解除されていることを確認することができます

{ 
    QMutexLocker locker(myMutex); 
    if(checkSomething()) 
    { 
     return; 
    } 
    doSomething(); 
} 

このコードは次のようになります

{ 
    mutex_lock(myMutex); 
    if(checkSomething()) 
    { 
     mutex_unlock(myMutex); 
     return; 
    } 
    doSomething(); 
    mutex_unlock(myMutex); 
} 

ブライアンなどが、 Nealは、checkSomething()doSomething()が例外をスローするケースは安全に処理しないと指摘しています。

QtのQMutexLockerする代わりに、STDのstd::lock_guardだろう。

+2

例外を考慮する場合、2つのコードスニペットは同等ではありません。それらを同等にするには、 'checkSomething'と' doSomething'の周りにtry/catchブロックを追加する必要があります。 RAIIを使用する最初の例を好む別の理由があります。 :) –

+0

良い点、@ BrianNeal。私は答えを更新しました。 Qtインフラストラクチャでは本当に必要なものではないので、例外を使わないようにしているので、他の人がそれらを考慮する必要があることを簡単に忘れてしまいます。 –

関連する問題