std :: lock_guard या std :: scoped_lock?


143

C ++ 17 ने एक नया लॉक क्लास बुलाया std::scoped_lock

प्रलेखन से देखते हुए यह पहले से मौजूद std::lock_guardवर्ग के समान है ।

क्या अंतर है और मुझे इसका उपयोग कब करना चाहिए?

जवाबों:


125

scoped_lockकी एक सख्ती से बेहतर संस्करण है lock_guardकि मनमाने ढंग से एक ही बार में mutexes सभी की संख्या (के रूप में ही गतिरोध-परिहार कलन विधि का उपयोग ताले std::lock)। नए कोड में, आपको केवल कभी भी उपयोग करना चाहिए scoped_lock

एकमात्र कारण lock_guardअभी भी मौजूद है संगतता के लिए। इसे केवल हटाया नहीं जा सकता था, क्योंकि इसका उपयोग वर्तमान कोड में किया जाता है। इसके अलावा, यह अपनी परिभाषा को बदलने के लिए अवांछनीय साबित हुआ (एकात्मक से वेरैडिक तक), क्योंकि यह भी एक अवलोकन योग्य है, और इसलिए तोड़ना, बदलना (लेकिन कुछ तकनीकी कारणों से)।


8
इसके अलावा, वर्ग टेम्पलेट तर्क कटौती के लिए धन्यवाद, आपको लॉक करने योग्य प्रकारों को भी सूचीबद्ध करने की आवश्यकता नहीं है।
निकोल बोलस

3
@ निकोलबोल: यह सच है, लेकिन यह भी लागू होता है lock_guard। लेकिन यह निश्चित रूप से गार्ड कक्षाओं को उपयोग करने के लिए थोड़ा आसान बनाता है।
केरेक एसबी

6
scoped_lock C ++ 17 केवल
शीतल शाह

1
जैसा कि यह c ++ 17 है, संगतता इसके अस्तित्व के लिए एक विशेष रूप से अच्छा कारण है। जब आप इस मानक से स्याही अभी भी सूख रहे हैं, तो "आपको केवल कभी उपयोग करना चाहिए" के किसी भी निरंकुश दावे से मैं असहमत हूं।
पॉल चिल्ड्स

88

एकल और महत्वपूर्ण अंतर यह है कि 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को एक विशेषज्ञता के रूप में लागू किया जा सकता है और इस तरह आपको संभावित प्रदर्शन मुद्दों के बारे में डरने की ज़रूरत नहीं है।

जीसीसी 7 के पास पहले से ही समर्थन है std::scoped_lockजिसके लिए यहां देखा जा सकता है

अधिक जानकारी के लिए आप मानक पेपर पढ़ना चाह सकते हैं


9
केवल 10 मिनट के बाद अपने खुद के सवाल का जवाब दिया। क्या आप वास्तव में नहीं जानते थे?
वाल्टर


3
जब मैंने इसे समिति में लाया, तो जवाब था "कुछ भी नहीं।" यह हो सकता है कि कुछ एल्गोरिथ्म के पतित मामले, यह बिल्कुल सही बात है। या यह हो सकता है कि पर्याप्त लोग गलती से कुछ भी लॉक न करें जब उनका इरादा किसी चीज़ को लॉक करने का हो तो यह एक आम समस्या है। मुझे यकीन नहीं हो रहा है।
हावर्ड हिनांट

3
@HowardHinnant: scoped_lock lk; // locks all mutexes in scope। LGTM।
केरेक एसबी

2
@KerrekSB: scoped_lock lk;के लिए नया आशुलिपि है scoped_lock<> lk;। वहाँ रहे हैं कोई mutexes। तो आप सही हैं। ;-)
हावर्ड हिनान्ट

26

देर से जवाब, और ज्यादातर के जवाब में:

आप std::lock_guardपदावनत विचार कर सकते हैं ।

उस सामान्य मामले के लिए जिसे किसी एक म्यूटेक्स को लॉक करने की आवश्यकता है, std::lock_guardएक एपीआई है जो उपयोग करने के लिए थोड़ा सुरक्षित है scoped_lock

उदाहरण के लिए:

{
   std::scoped_lock lock; // protect this block
   ...
}

उपरोक्त स्निपेट में आकस्मिक रन-टाइम त्रुटि होने की संभावना है क्योंकि यह संकलन करता है और फिर बिल्कुल कुछ नहीं करता है। कोडर शायद मतलब है:

{
   std::scoped_lock lock{mut}; // protect this block
   ...
}

अब यह लॉक / अनलॉक हो जाता है mut

यदि lock_guardइसके बजाय ऊपर के दो उदाहरणों में उपयोग किया गया था, तो पहला उदाहरण रन-टाइम त्रुटि के बजाय एक संकलन-समय त्रुटि है, और दूसरा उदाहरण संस्करण की समान कार्यक्षमता है जो उपयोग करता है scoped_lock

इसलिए मेरी सलाह है कि नौकरी के लिए सबसे सरल टूल का उपयोग करें:

  1. lock_guard यदि आपको संपूर्ण दायरे के लिए ठीक 1 म्यूटेक्स को लॉक करने की आवश्यकता है।

  2. scoped_lock यदि आपको कई म्यूटेक्स को लॉक करने की आवश्यकता है जो कि ठीक 1 नहीं है।

  3. unique_lockयदि आपको ब्लॉक के दायरे में अनलॉक करने की आवश्यकता है (जिसमें उपयोग शामिल है condition_variable)।

यह सलाह का अर्थ यह नहीं है कि scoped_lock0 म्यूटेक्स को स्वीकार नहीं करने के लिए फिर से डिज़ाइन किया जाना चाहिए। ऐसे वैध उपयोग के मामले मौजूद हैं जहां यह scoped_lockवैरेडिक टेम्प्लेट पैरामीटर पैक को स्वीकार करने के लिए वांछनीय है जो खाली हो सकता है। और खाली मामले को कुछ भी लॉक नहीं करना चाहिए ।

और इसीलिए lock_guardपदावनत नहीं किया जाता है। scoped_lock और unique_lock की कार्यक्षमता का सुपरसेट हो सकता है lock_guard, लेकिन यह तथ्य एक दोधारी तलवार है। कभी-कभी यह उतना ही महत्वपूर्ण होता है जितना एक प्रकार क्या नहीं करेगा (इस मामले में डिफ़ॉल्ट निर्माण)।


13

यहाँ क्रिया में C ++ Concurrency से एक नमूना और उद्धरण है :

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::lockc ++ 17 से पहले अब का उपयोग कर लिखा जा सकता है std::scoped_lockगलतियों के लिए कम क्षमता के साथ, है, जो केवल एक अच्छी बात हो सकती है!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.