C ++ 17 wprowadził nową klasę blokady o nazwie std::scoped_lock
.
Sądząc po dokumentacji, wygląda podobnie do już istniejącej std::lock_guard
klasy.
Jaka jest różnica i kiedy powinienem go używać?
c++
multithreading
locking
c++17
Stephan Dollberg
źródło
źródło
lock_guard
. Ale z pewnością sprawia, że klasy strażników są nieco łatwiejsze w użyciu.Jedyną i ważną różnicą jest to, że
std::scoped_lock
konstruktor wariadyczny przyjmuje więcej niż jeden muteks. Pozwala to na zablokowanie wielu muteksów w zakleszczeniu, unikając w ten sposób, jakbystd::lock
były używane.Wcześniej trzeba było wykonać mały taniec, aby zablokować wiele muteksów w bezpieczny sposób, używając,
std::lock
jak wyjaśniono w tej odpowiedzi .Dodanie blokady zakresu ułatwia korzystanie z niego i pozwala uniknąć powiązanych błędów. Możesz uznać za
std::lock_guard
przestarzałe. Pojedynczy przypadek argumentustd::scoped_lock
może zostać zaimplementowany jako specjalizacja i nie musisz się obawiać o ewentualne problemy z wydajnością.GCC 7 ma już wsparcie,
std::scoped_lock
które można zobaczyć tutaj .Aby uzyskać więcej informacji, możesz przeczytać standardowy artykuł
źródło
scoped_lock lk; // locks all mutexes in scope
. LGTM.scoped_lock lk;
to nowy skrót dlascoped_lock<> lk;
. Nie są żadne muteksy. Więc masz rację. ;-)Późna odpowiedź, głównie w odpowiedzi na:
W typowym przypadku, gdy trzeba zablokować dokładnie jeden muteks,
std::lock_guard
ma API, które jest trochę bezpieczniejsze w użyciu niżscoped_lock
.Na przykład:
Powyższy fragment kodu jest prawdopodobnie przypadkowym błędem w czasie wykonywania, ponieważ kompiluje się, a następnie nie robi absolutnie nic. Koder prawdopodobnie miał na myśli:
Teraz blokuje / odblokowuje
mut
.Jeśli
lock_guard
zamiast tego został użyty w dwóch powyższych przykładach, pierwszy przykład jest błędem czasu kompilacji zamiast błędu czasu wykonywania, a drugi przykład ma identyczną funkcjonalność jak wersja, która używascoped_lock
.Więc radzę użyć najprostszego narzędzia do pracy:
lock_guard
jeśli chcesz zablokować dokładnie 1 muteks dla całego zakresu.scoped_lock
jeśli chcesz zablokować liczbę muteksów, która nie jest dokładnie 1.unique_lock
jeśli potrzebujesz odblokować w zakresie bloku (co obejmuje użycie z acondition_variable
).Ta rada ma nie oznacza, że
scoped_lock
powinna zostać zmieniona, aby nie akceptować 0 muteksy. Istnieją ważne przypadki użycia, w których pożądanescoped_lock
jest akceptowanie pakietów parametrów szablonów z różnymi szablonami, które mogą być puste. A pusta obudowa nie powinna niczego blokować.I dlatego
lock_guard
nie jest przestarzały.scoped_lock
iunique_lock
może być nadzbiorem funkcjonalnościlock_guard
, ale fakt ten jest mieczem obosiecznym. Czasami jest równie ważne, czego typ nie będzie robił (w tym przypadku konstrukcja domyślna).źródło
Oto przykład i cytat z C ++ Concurrency in Action :
vs.
źródło