2009-06-27 16 views
13

मुझे याद है कि विधियों के अंदर घोषित स्थिर चर को थ्रेड-सुरक्षित नहीं है। (What about the Meyer's singleton? देखें के रूप में Todd Gardner ने उल्लेख किया)म्यूटक्सिंग के बिना थ्रेड-सुरक्षित स्थिर चर?

Dog* MyClass::BadMethod() 
{ 
    static Dog dog("Lassie"); 
    return &dog; 
} 

मेरे पुस्तकालय अपने आवेदन के हिस्से के रूप संकलित करने के लिए उत्पन्न करता है सी ++ अंत उपयोगकर्ताओं के लिए कोड। जो कोड उत्पन्न करता है उसे थ्रेड-सुरक्षित क्रॉस-प्लेटफ़ॉर्म तरीके से स्थिर चर प्रारंभ करने की आवश्यकता होती है। मैं वैरिएबल प्रारंभिकता को म्यूटेक्स करने के लिए boost::call_once का उपयोग करना चाहता हूं लेकिन फिर अंतिम उपयोगकर्ता बूस्ट निर्भरता के संपर्क में आते हैं।

क्या अंत उपयोगकर्ताओं पर अतिरिक्त निर्भरताओं को मजबूर किए बिना ऐसा करने का कोई तरीका है?

+0

आप अपने आप में बूस्ट लाइब्रेरीज़ में भी स्थिर रूप से लिंक कर सकते हैं, फिर आप अपने उपयोगकर्ताओं को असुविधाजनक डर के बिना जो कुछ भी चाहते हैं उसे बढ़ावा दे सकते हैं। – Ben

+0

संभावित डुप्लिकेट [क्या स्थानीय स्थैतिक वैरिएबल प्रारंभिक थ्रेड-सुरक्षित सी ++ 11 में है?] (Http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe-in-c11) –

+1

@LucianAdrianGrijincu, यह प्रश्न सी ++ 11 (इसे 200 9 में पोस्ट किया गया था) की भविष्यवाणी करता है, हालांकि आपका प्रश्न संबंधित है, यह सख्त डुप्लिकेट नहीं है। लिंक के लिए धन्यवाद। – Gili

उत्तर

10

आप सही है कि इस तरह स्थिर आरंभीकरण सुरक्षित थ्रेड नहीं है

फिलहाल (here पर चर्चा क्या संकलक यह में बदल जाएगी एक लेख है) कर रहे हैं, वहाँ कोई मानक, धागा सुरक्षित, पोर्टेबल प्रारंभ करने में जिस तरह से है स्थिर सिंगलेट्स। डबल चेक लॉकिंग का उपयोग किया जा सकता है, लेकिन आपको संभावित गैर-पोर्टेबल थ्रेडिंग लाइब्रेरी की आवश्यकता है (चर्चा here देखें)।

यहां कुछ विकल्प है धागा सुरक्षा बहुत जरूरी है यदि:

  1. लेज़ी मत बनो (लोड): स्थिर आरंभीकरण के दौरान प्रमाणित करें। यह एक समस्या हो सकती है यदि कोई अन्य स्थैतिक इस कन्स्ट्रक्टर में इस फ़ंक्शन को कॉल करता है, क्योंकि स्थैतिक प्रारंभिकरण का क्रम अनिर्धारित है (here देखें)।
  2. उपयोग को बढ़ावा देने (के रूप में आपने कहा था) या लोकी
  3. रोल अपने खुद सिंगलटन अपने समर्थित प्लेटफार्मों पर (शायद बचा जाना चाहिए जब तक कि आप एक सूत्रण विशेषज्ञ हैं)
  4. लॉक एक म्युटेक्स हर आप का उपयोग की जरूरत है। यह बहुत धीमा हो सकता है।

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

// in a cpp: 
namespace { 
    Dog dog("Lassie"); 
} 

Dog* MyClass::BadMethod() 
{ 
    return &dog; 
} 

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

Dog* MyClass::BadMethod() 
{ 
    static scoped_ptr<Dog> pdog; 
    { 
    Lock l(Mutex); 
    if(!pdog.get()) 
     pdog.reset(new Dog("Lassie")); 
    } 
    return pdog.get(); 
} 
+0

मैंने बुलेट काटने और 'बूस्ट :: call_once() ' – Gili

+7

का उपयोग करके यह जवाब अब अप्रचलित कर दिया है: http://stackoverflow.com/questions/8102125/is-local-static-variable-initialization-thread-safe- में-C11 – Yankes

2

एक ही रास्ता मैं गारंटी करने के लिए आप अपने "static Dog" तरह गैर संरक्षित संसाधनों के साथ सूत्रण मुद्दों के लिए नहीं होगा की पता है कि यह एक आवश्यकता है कि वे सभी instantiated रहे से पहले किसी भी धागे बनाए जाते हैं बनाने के लिए है।

यह दस्तावेज के रूप में इतना आसान हो सकता है कि उन्हें कुछ और करने से पहले मुख्य धागे में MyInit() फ़ंक्शन को कॉल करना होगा। फिर आप MyInit() का निर्माण प्रत्येक प्रकार के एक ऑब्जेक्ट को तत्काल और नष्ट करने के लिए करते हैं जिसमें उनमें से एक statics शामिल है।

एकमात्र अन्य विकल्प यह है कि वे आपके जेनरेट कोड का उपयोग कैसे कर सकते हैं (बूस्ट, विन 32 धागे, आदि का उपयोग करें) पर एक और प्रतिबंध डालना है। इनमें से कोई भी समाधान मेरी राय में स्वीकार्य है - नियमों को उत्पन्न करना ठीक है कि उन्हें पालन करना होगा।

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

3

एक तरह से आप यह कर सकते हैं कि धागा सुरक्षा के लिए एक म्युटेक्स की आवश्यकता नहीं है, सिंगलटन एक फ़ाइल स्थिर बनाने के लिए है न कि समारोह स्थिर से:

static Dog dog("Lassie"); 
Dog* MyClass::BadMethod() 
{ 
    return &dog; 
} 

Dog उदाहरण मुख्य थ्रेड से पहले initialised किया जाएगा रन। फ़ाइल स्थिर चर के प्रारंभिक क्रम के साथ एक प्रसिद्ध मुद्दा है, लेकिन जब तक कुत्ता किसी अन्य अनुवाद इकाई में परिभाषित किसी भी अन्य सांख्यिकी पर भरोसा नहीं करता है, तो यह चिंता का विषय नहीं होना चाहिए।

+0

मुझे याद है कि यदि आपके पास विंडोज़ पर डीएलएल में ग्लोबल स्टार्टिस्टर्स हैं तो समस्याएं हो सकती हैं - लेकिन मुझे विशिष्टताओं को याद नहीं किया जा सकता है, और यदि कोड डीएलएल में है तो यह वास्तव में केवल प्रासंगिक है: डी – olliej

+0

मेरा कोड * करता है * एक डीएलएल :) मुझे किस समस्या के बारे में पता होना चाहिए? – Gili

+0

अगर मुझे पता है तो darned। मेरा सबसे अच्छा अनुमान है कि कन्स्ट्रक्टर प्रत्येक बार डीएल लोड होने के लिए एक बार चलाएगा, इसलिए यदि डीएलएल को अनलोड किया गया है और फिर से लोड किया गया है तो इसे फिर से बनाया जाएगा, इसलिए यह सिंगलटन "कॉन्ट्रैक्ट" को तोड़ देता है लेकिन आप –

2

AFAIK, केवल समय इस सुरक्षित रूप से mutexes या वैश्विक उदाहरणों की पूर्व initialisation मैथ्यू में है के बिना किया गया है और विल्सन का Imperfect C++, जो चर्चा करता है कि "स्पिन म्यूटेक्स" का उपयोग करके इसे कैसे किया जाए। मैं इसकी प्रतिलिपि के करीब नहीं हूं, इसलिए इस समय आपको और अधिक सटीक नहीं बता सकता।

आईआईआरसी, STLSoft पुस्तकालयों के अंदर इसका उपयोग करने के कुछ उदाहरण हैं, हालांकि मुझे इस समय कौन से घटक याद नहीं हैं।

4

यह सुनिश्चित नहीं है कि यह आपका मतलब है या नहीं, लेकिन आप इसके बजाय pthread_once पर कॉल करके POSIX सिस्टम पर बढ़ावा निर्भरता को हटा सकते हैं। मुझे लगता है कि आपको विंडोज़ पर कुछ अलग करना होगा, लेकिन इससे बचने के लिए यही कारण है कि बूस्ट में पहली जगह थ्रेड लाइब्रेरी है, और लोग इसके आधार पर कीमत का भुगतान क्यों करते हैं।

कुछ भी "थ्रेड-सुरक्षित" करना आपके थ्रेड कार्यान्वयन के साथ अंतर्निहित रूप से बाध्य है। आपको पर कुछ पर निर्भर होना है, भले ही यह केवल प्लेटफॉर्म-निर्भर स्मृति मॉडल हो। शुद्ध सी ++ 03 में धागे के बारे में कुछ भी मानना ​​संभव नहीं है, जो भाषा के दायरे से बाहर हैं।

संबंधित मुद्दे