C ++ 17は新しいロッククラスを導入しました std::scoped_lock
。
ドキュメントから判断すると、既存のstd::lock_guard
クラスに似ています。
違いは何ですか?いつ使用する必要がありますか?
C ++ 17は新しいロッククラスを導入しました std::scoped_lock
。
ドキュメントから判断すると、既存のstd::lock_guard
クラスに似ています。
違いは何ですか?いつ使用する必要がありますか?
回答:
scoped_lock
より厳密に優れたバージョンであるlock_guard
すべての(同じデッドロック回避アルゴリズムを使用して、一度にミューテックスの任意の数をロックしていますstd::lock
)。新しいコードでは、のみを使用してくださいscoped_lock
。
lock_guard
まだ存在する唯一の理由は、互換性のためです。現在のコードで使用されているため、単に削除することはできません。さらに、その定義を(単項から可変に)変更することは望ましくないことがわかりました。
lock_guard
。しかし、それは確かにガードクラスを少し使いやすくします。
単一の重要な違いはstd::scoped_lock
、可変個のコンストラクターが複数のミューテックスを取ることです。これにより、まるでstd::lock
使用されたかのように、デッドロックを回避して複数のミューテックスをロックできます。
{
// safely locked as if using std::lock
std::scoped_lock<std::mutex, std::mutex> lock(mutex1, mutex2);
}
以前は、この回答std::lock
を説明したように使用して、安全な方法で複数のミューテックスをロックするために少しダンスをする必要がありました。
スコープロックの追加により、これが使いやすくなり、関連するエラーが回避されます。std::lock_guard
非推奨と見なすことができます。の単一引数のケースはstd::scoped_lock
特殊化として実装できるため、パフォーマンスの問題の可能性について心配する必要はありません。
GCC 7にはすでにサポートがstd::scoped_lock
あり、ここで確認できます。
詳細については、標準的なペーパーを読むことをお勧めします
scoped_lock lk; // locks all mutexes in scope
。LGTM。
scoped_lock lk;
の新しい省略形ですscoped_lock<> lk;
。ありません何のミューテックスが。だからあなたは正しい。;-)
遅い答え、そして大部分は以下に対応します:
std::lock_guard
非推奨と見なすことができます。
ミューテックスを1つだけロックする必要があるという一般的なケースでstd::lock_guard
は、を使用するよりも少し安全なAPIがありますscoped_lock
。
例えば:
{
std::scoped_lock lock; // protect this block
...
}
上記のスニペットは、コンパイルしてまったく何もしないため、偶発的な実行時エラーの可能性があります。コーダーはおそらく意味しました:
{
std::scoped_lock lock{mut}; // protect this block
...
}
これでロック/ロック解除されmut
ます。
lock_guard
上記の2つの例で使用された場合、最初の例は実行時エラーではなくコンパイル時エラーであり、2番目の例はを使用するバージョンと同じ機能を備えていますscoped_lock
。
だから私のアドバイスは、仕事に最も簡単なツールを使うことです:
lock_guard
スコープ全体で1つのmutexをロックする必要がある場合。
scoped_lock
正確に1ではない複数のミューテックスをロックする必要がある場合。
unique_lock
ブロックの範囲内でロックを解除する必要がある場合(これには、 condition_variable
)。
このアドバイスは 、0ミューテックスを受け入れないように再設計する必要があることを意味するものではありませんscoped_lock
。scoped_lock
空である可能性のある可変テンプレートテンプレートパックを受け入れることが望ましい有効な使用例が存在します。そして、空のケースはすべきではありません何もロックして。
そして、それlock_guard
がが非推奨ではない理由です。 scoped_lock
と unique_lock
の機能のスーパーセットかもしれませんlock_guard
が、その事実は両刃の剣です。型が行わないことが同じくらい重要な場合があります(この場合、デフォルトの構成)。
以下は、C ++の同時実行性のサンプルと引用です。
friend void swap(X& lhs, X& rhs)
{
if (&lhs == & rhs)
return;
std::lock(lhs.m, rhs.m);
std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock);
std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock);
swap(lhs.some_detail, rhs.some_detail);
}
対
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::scoped_lock guard(lhs.m, rhs.m);
swap(lhs.some_detail, rhs.some_detail);
}
が存在
std::scoped_lock
するということは、std::lock
c ++ 17より前に使用していたほとんどのケースがを使用して記述できるようになりstd::scoped_lock
、間違いの可能性が少なくなるということです。