web-dev-qa-db-ja.com

std :: unique_lock <std :: mutex>またはstd :: lock_guard <std :: mutex>

2つのユースケースがあります。

A. 2つのスレッドによるアクセスをキューに同期させたいのですが。

B. 2つのスレッドによるキューへのアクセスを同期させ、条件変数を使用します。スレッドの1つが、他のスレッドによってキューに格納されるコンテンツを待機するためです。

ユースケースAでは、 std::lock_guard<> を使用したコード例を参照してください。ユースケースBでは、 std::unique_lock<> を使ったコード例を見てください。

両者の違いは何ですか?また、どちらのユースケースでどちらを使用すればよいですか?

301
chmike

違いは、std::unique_lockをロックおよびロック解除できることです。 std::lock_guardは構築時に一度だけロックされ、破棄時にロック解除されます。

そのため、ユースケースBでは、条件変数にstd::unique_lockが必ず必要です。ケースAの場合、それはあなたがガードを再ロックする必要があるかどうかによって異なります。

std::unique_lockには他の機能があります。例えば:ミューテックスを直ちにロックせずにRAIIラッパーを構築することです( here を参照)。

std::lock_guardは便利なRAIIラッパーも提供しますが、複数のミューテックスを安全にロックすることはできません。限定された範囲のラッパーが必要な場合に使用できます。例えば、メンバー関数です。

class MyClass{
    std::mutex my_mutex;
    void member_foo() {
        std::lock_guard<mutex_type> lock(this->my_mutex);            
        /*
         block of code which needs mutual exclusion (e.g. open the same 
         file in multiple threads).
        */

        //mutex is automatically released when lock goes out of scope           
};

Chmikeによる質問を明確にするために、デフォルトではstd::lock_guardstd::unique_lockは同じです。したがって、上記の場合、std::lock_guardstd::unique_lockに置き換えることができます。ただし、std::unique_lockには、もう少しオーバーヘッドがあります。

最近ではstd::scoped_lockの代わりに std::lock_guard を使うべきです。

289
inf

lock_guardunique_lockはほとんど同じものです。 lock_guardは制限されたインターフェースを持つ制限されたバージョンです。

lock_guardは常にその構造から破壊までロックをかけています。 unique_lockはすぐにロックすることなく作成することができ、その存在下の任意の時点でロックを解除することができ、そしてロックの所有権をあるインスタンスから別のインスタンスに移すことができます。

そのため、lock_guardの機能が必要でない限り、常にunique_lockを使用します。 condition_variableunique_lockを必要とします。

100
Sebastian Redl

unlockを破壊することなく、その間のミューテックスを手動でlockできるようにする必要がない限り、lock_guardを使用してください。

特にcondition_variableは、waitの呼び出しでスリープするときにミューテックスのロックを解除します。だからこそlock_guardだけでは不十分です。

40
ComicSansMS

lock_guardunique_lockの間には共通点がいくつかありますが、違いもあります。

しかし、質問の文脈では、コンパイラーはlock_guardを条件変数と組み合わせて使用​​することを許可しません。スレッドが条件変数でwaitを呼び出すと、mutexが自動的にロック解除され、他のスレッドがスレッドが呼び出され(待ち状態から抜け出し)、ロックが再獲得されます。

この現象はlock_guardの原則に反しています。 lock_guardは一度だけ構築でき、一度だけ破壊できます。

したがって、lock_guardを条件変数と組み合わせて使用​​することはできませんが、unique_lockを使用することはできます(unique_lockを何度もロックおよびロック解除できるため)。

9
Sandeep