web-dev-qa-db-ja.com

boost :: unique_lock vs boost :: lock_guard

これら2つのロッククラスの違いはよくわかりません。 Boostドキュメントでは、_boost::unique_lock_はロックを自動的に認識しないと言われています。

_unique_lock_と_lock_guard_の主な違いは、_unique_lock_でlock()関数を明示的に呼び出す必要があるということですか?

58
Guillaume07

最初に質問に答えてください。いいえ、unique_lockでlockを呼び出す必要はありません。下記参照:

Unique_lockは、より多くの機能を備えたロッククラスです。ほとんどの場合、lock_guardは必要なことを行い、十分です。
unique_lockには、さらに多くの機能が用意されています。たとえば、タイムアウトが必要な場合、またはオブジェクトの構築よりも後の時点までロックを延期したい場合は、一定時間待機します。ですから、何をしたいかに大きく依存します。ところで:次のコードスニペットは同じことをします。

boost::mutex mutex;
boost::lock_guard<boost::mutex> lock(mutex);
boost::mutex mutex;
boost::unique_lock<boost::mutex> lock(mutex);

最初のものはデータへのアクセスを同期するために使用できますが、条件変数を使用する場合は、2番目のものを使用する必要があります。

60
mkaes

現時点で最良の投票された答えは良いですが、もう少し深く掘り下げるまで疑問を明確にしなかったので、同じボートに乗っているかもしれない人々と共有することにしました。

まず、lock_guardunique_lockの両方がRAIIパターンに従います。最も単純な使用例では、構築中にロックが取得され、破棄中に自動的にロック解除されます。それがあなたのユースケースであるなら、あなたはunique_lockの余分な柔軟性を必要とせず、lock_guardはより効率的です。

両者の主な違いは、unique_lockインスタンスは、関連付けられているmutexを常に所有する必要はなく、lock_guardではmutexを所有していることです。これは、unique_lockがロックを所有しているかどうかを示す追加のフラグと、それをチェックする別の追加メソッド 'owns_lock()'が必要であることを意味します。これを知っているので、このフラグがもたらす追加の利点をすべて説明し、追加のデータのオーバーヘッドを設定およびチェックします。

  1. ロックは構築時に正しく実行する必要はありません。構築中にstd::defer_lockフラグを渡して、構築中にミューテックスのロックを解除したままにすることができます。
  2. 関数が終了する前にロックを解除でき、デストラクタが解放するのを必ずしも待つ必要はありません。これは便利です。
  3. ロックの所有権を関数から渡すことができます。これはmovableであり、copyableではありません。
  4. 条件の待機中にミューテックスをロック、条件チェック、およびロック解除する必要があるため、条件変数で使用できます。
44
jayadev

それらの実装は、パス.../boost/thread/locks.hppにあります-そして、それらは次々に並んでいます:)

lock_guardは、コンストラクターで相互排他ロックをロックし、デストラクタでロック解除する、簡単なユーティリティクラスです。詳細は気にしません。

nique_lockはかなり複雑な機能で、多くの機能が追加されていますが、コンストラクターで自動的にロックされます。 unique_lockと呼ばれるのは、「所有権のロック」の概念が導入されているためです(owns_lock()メソッドを参照)。

14

pthreads(3)に慣れている場合:

  • boost::mutex = pthread_mutex_*
  • boost::unique_lock = pthread_rwlock_*書き込み/排他ロックの取得に使用(つまりpthread_rwlock_wrlock
  • boost::shared_lock = pthread_rwlock_*読み取り/共有ロックの取得に使用(つまりpthread_rwlock_rdlock

はい、boost::unique_lockおよびboost::mutexは同様の方法で機能しますが、boost::mutexは一般に、取得および解放するためのより軽いmutexです。つまり、shared_lock既にロックを取得している方が高速ですが(同時実行が可能です)、unique_lock

実装の詳細を見るにはカバーの下を見る必要がありますが、それは意図した違いの要点です。


パフォーマンスといえば、ここにレイテンシーの比較的便利な比較があります:

http://www.eecs.berkeley.edu/%7Ercs/research/interactive_latency.html

I /誰かが異なるpthread_ *プリミティブの相対的なコストをベンチマークできればいいのですが、最後に見たところ、pthread_mutex_*は約25usでしたが、pthread_rwlock_*は、読み取りロックがすでに取得されている(〜10us)か、取得されていない(〜20us)か、ライター(〜100us)かによって、20〜100usでした。現在の数値を確認するにはベンチマークを行う必要がありますが、これは非常にOS固有のものであると確信しています。

6
Sean

Unique_lockは、一意ロックと共有ロックの違いを強調する必要がある場合にも使用できると思います。

1
Alexey Petrenko