C ++ 17 adlı yeni bir kilit sınıfı tanıttı std::scoped_lock
.
Belgelerden yola çıkarak, zaten var olan std::lock_guard
sınıfa benziyor .
Ne fark eder ve ne zaman kullanmalıyım?
C ++ 17 adlı yeni bir kilit sınıfı tanıttı std::scoped_lock
.
Belgelerden yola çıkarak, zaten var olan std::lock_guard
sınıfa benziyor .
Ne fark eder ve ne zaman kullanmalıyım?
Yanıtlar:
Bu scoped_lock
, kesinlikle lock_guard
aynı anda muteks sayısını kilitleyen, aynı kilitlenme önleme algoritmasını kullanarak kesin olarak üstün bir versiyonudur std::lock
. Yeni kodda, yalnızca hiç kullanmamalısınız scoped_lock
.
lock_guard
Halen var olmanın tek nedeni uyumluluktur. Geçerli kodda kullanıldığı için sadece silinemedi. Dahası, tanımını değiştirmek (istenmeyenlerden varadiklere) istenmeyen bir durumdu, çünkü bu da gözlemlenebilir ve dolayısıyla kırıcı bir değişikliktir (ancak bir şekilde teknik nedenlerden dolayı).
lock_guard
. Ancak koruma sınıflarının kullanımını biraz daha kolaylaştırıyor.
Tek ve önemli fark, std::scoped_lock
birden fazla muteksi alan değişken bir kurucuya sahip olmasıdır. Bu, sanki std::lock
kullanılmış gibi kaçınarak birden fazla muteksi kilitlenerek kilitlemeye izin verir .
{
// safely locked as if using std::lock
std::scoped_lock<std::mutex, std::mutex> lock(mutex1, mutex2);
}
Daha önce bu cevabıstd::lock
açıkladığı gibi birden fazla muteksi güvenli bir şekilde kilitlemek için küçük bir dans yapmak zorundaydınız .
Kapsam kilidinin eklenmesi bunu kullanmayı kolaylaştırır ve ilgili hataları önler. Kullanımdan std::lock_guard
kaldırılmış olarak değerlendirebilirsiniz. Tek argüman örneği std::scoped_lock
bir uzmanlık alanı olarak uygulanabilir ve bu nedenle olası performans sorunlarından korkmanıza gerek kalmaz.
GCC 7 zaten buradastd::scoped_lock
görülebilen desteğe sahip .
Daha fazla bilgi için standart kağıdı okumak isteyebilirsiniz
scoped_lock lk; // locks all mutexes in scope
. LGTM.
scoped_lock lk;
için yeni kestirme yol scoped_lock<> lk;
. Orada olan hiçbir muteksler. Yani haklısın. ;-)
Geç cevap ve çoğunlukla aşağıdakilere yanıt olarak:
Kullanımdan
std::lock_guard
kaldırılmış olarak değerlendirebilirsiniz.
Bir kişinin tam olarak bir muteksi kilitlemesi gerektiği genel durum std::lock_guard
için, kullanmaktan biraz daha güvenli bir API'ye sahiptir scoped_lock
.
Örneğin:
{
std::scoped_lock lock; // protect this block
...
}
Yukarıdaki snippet muhtemelen yanlışlıkla bir çalışma zamanı hatasıdır çünkü derler ve sonra kesinlikle hiçbir şey yapmaz. Kodlayıcı muhtemelen:
{
std::scoped_lock lock{mut}; // protect this block
...
}
Şimdi kilitleniyor / kilidini açıyor mut
.
Eğer lock_guard
bunun yerine, yukarıdaki iki örnekte kullanılmıştır, ilk örnek yerine çalıştırma hatası bir derleme hatası olduğu, ve ikinci bir örneği kullanımları versiyonu olarak aynı özelliğe sahip scoped_lock
.
Bu yüzden tavsiyem iş için en basit aracı kullanmaktır:
lock_guard
tüm kapsam için tam olarak 1 muteksi kilitlemeniz gerekiyorsa.
scoped_lock
tam olarak olmayan bir dizi muteksi kilitlemeniz gerekiyorsa 1.
unique_lock
blok kapsamında kilidini açmanız gerekiyorsa (a ile birlikte kullanım içerir condition_variable
).
Bu tavsiye etmez değil ima scoped_lock
0 muteksleri kabul etmeyecek şekilde yeniden dizayn edilmelidir. scoped_lock
Boş olabilecek değişken şablon parametre paketlerini kabul etmenin istendiği geçerli kullanım örnekleri vardır . Ve boş durumda olmalıdır değil bir şey kilitleyin.
İşte bu yüzden lock_guard
itiraz edilmiyor. scoped_lock
ve unique_lock
işlevselliğinin bir üst kümesi olabilir lock_guard
, ama bu gerçek iki ucu keskin bir kılıçtır. Bazen bir türün ne yapmayacağı da önemlidir (bu durumda varsayılan yapı).
İşte C ++ Concurrency in Action'dan bir örnek ve alıntı :
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);
}
vs.
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);
}
Araçların varlığı, c ++ 17'den önce kullanacağınız
std::scoped_lock
çoğu vakanın , sadece daha iyi bir şey olabilen hatalar için daha az potansiyelstd::lock
kullanarak kullanılarak yazılabileceği anlamına gelirstd::scoped_lock
!