2012-05-07 19 views
11

वे कहते हैं कि प्रारंभिक बाध्यकारी सिंक्रनाइज़ेशन की समस्या हल करती है। मैं समझ नहीं पाया "कैसे"। क्या यह जावा के लिए कुछ खास है या यह भी सी ++ पर लागू होता है?सिंगलटन पैटर्न - प्रारंभिक बाध्यकारी (स्थिर चर के साथ) म्यूटेक्स ताले की आवश्यकता को कम करता है?

तो, इस विधि के साथ हमें वास्तव में एक म्यूटेक्स लॉक की आवश्यकता नहीं होगी?

enter image description here

+1

दिलचस्प, कभी नहीं इसे उस तरह से इस्तेमाल करने के बारे में सोचा। मैंने हमेशा 'if (instance == null) उदाहरण = नया सिंगलटन();' का उपयोग किया। यह देखने के लिए प्रतीक्षा करें कि विशेषज्ञों को क्या कहना है –

+0

उपरोक्त टिप्पणी सही है, इस तरह स्मृति को बचाया जा सकता है। क्योंकि जब पहला अनुरोध आता है तब वस्तु उत्पन्न की जाएगी। –

+0

यह कुछ प्रकाश फेंक सकता है http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pterntern-Part-I/4/ – DumbCoder

उत्तर

3

मुझे लगता है कि वे किसी भी थ्रेड को शुरू करने/बनाने से पहले सिंगलटन इंस्टेंस बनाने का जिक्र कर रहे हैं, इस प्रकार सृजन पर सिंक्रनाइज़ेशन की आवश्यकता को कम करता है।

संपादित: और स्थैतिक चर

सी ++ में सी के बारे में जानकारी ++ जोड़ने, स्थैतिक चर भी प्रारंभ कर रहे हैं इससे पहले कि डेविड Harkness तरह निष्पादन जावा के लिए उल्लेख है। सी ++ में इसके साथ एक मुद्दा एम्बेडेड वातावरण में हो सकता है जहां सिस्टम प्रारंभ होने के बाद तक malloc/new cant को कॉल नहीं किया जा सकता है, इस मामले में सिंगलटन स्थिर प्रारंभकर्ता का उपयोग समस्याग्रस्त हो सकता है।

+0

@ अनीश, क्या आप "डेविड हार्नेस" का जिक्र कर रहे हैं जिसने आपके प्रश्न का उत्तर दिया है, जिसे आपने स्वीकार किया है, या सी ++ का संदर्भ है? – Brady

+0

नहीं, मैं एक सी ++ संदर्भ के बारे में बात कर रहा था। लेकिन फिर, मैंने सोचा कि मुझे कुछ काम भी करना चाहिए। :) –

+0

@ अनीशा, यदि आप स्टैक ओवरफ्लो में खोज करते हैं, तो संबंधित प्रश्नों के भार हैं। – Brady

-2

मामले में है कि आप चाहते हैं कि singelton सदस्य पहली कॉल जब तक रिक्त रहेगा, आप केवल निर्माण सिंक कर सकते हैं। उदाहरण के लिए

getInstance() { 
    if (singleton == null) { 
     lock(); 
     if (singleton == null) { 
       singleton = new Singleton(); 
     } 
     unlock(); 
    } 
    return singleton; 
} 
+3

यह कोड गलत और खतरनाक है। Http://en.wikipedia.org/wiki/Double-checked_locking – interjay

+0

देखें आपका समाधान थ्रेड सुरक्षित नहीं है। ऐसा होगा यदि आपने '(सिंगलटन == नल) 'चेक से पहले' लॉक() 'कॉल किया था, और' if' ब्लॉक के बाद' अनलॉक() 'कॉल किया था लेकिन वह लॉक()/अनलॉक () प्रत्येक 'getInstance()' कॉल के लिए ओवरहेड। –

+0

-1 इंटरजे के अनुसार, यह कोड और संबंधित डबल-चेक किए गए लॉकिंग * थ्रेड-सुरक्षित नहीं हैं *। –

11

JVM सुनिश्चित करता है कि प्रत्येक वर्ग पूरी तरह से अन्य धागे के माध्यम से इसे करने के लिए किसी भी उपयोग अनुमति देने से पहले भरी हुई है। इसका मतलब है कि ऊपर दिए गए uniqueInstance समेत सभी स्थैतिक चर, पूरी तरह से तुरंत पहुंचने से पहले उन्हें एक्सेस किया जा सकता है। यह जावा के लिए विशिष्ट है और इसका मतलब है कि आपको उदाहरण के प्रकाशन की सुरक्षा के लिए सिंक्रनाइज़ेशन की आवश्यकता नहीं है।

+0

पुष्टिकरण के लिए धन्यवाद, और यह भी बता रहा है कि यह सब "जावा" के लिए बिल्कुल विशिष्ट है। –

+0

सी # की समान गारंटी है। –

+0

मैं * सोचता हूं * पूरी तरह से थ्रेडसेफ होने के लिए आपको फ़ील्ड 'अंतिम' को चिह्नित करने की आवश्यकता है। हालांकि JVM स्थिर चर के प्रारंभ को लागू करता है, मेरा मानना ​​है कि जेवीएम के लिए स्मृति बाधा को उत्सर्जित करना संभव नहीं है, जिसका अर्थ यह होगा कि एक और थ्रेड एक प्रारंभिक स्थिति में स्थैतिक क्षेत्र का निरीक्षण कर सकता है। –

0

उत्तर YES! है। इस विधि के साथ आपको "उदाहरण प्राप्त करें"
--Edit--
कारण यह है कि ऑब्जेक्ट का निर्माण ओएस द्वारा लोडिंग प्रक्रिया का हिस्सा है जो आपके कोड से पहले लोड होने की गारंटी देता है चल रहा है।
पी। यह सी ++ पर भी लागू होगा।
नोट्स:
1. आपको "उदाहरण प्राप्त करने" के लिए लॉक की आवश्यकता नहीं होगी, लेकिन उदाहरण के साझा सदस्य होने पर आपको आवश्यकता हो सकती है।
2. यह केवल तभी संभव है जब आपको इंस्टेंस के प्रारंभ के लिए पैरामीटर की आवश्यकता न हो।

+0

यह उपयोगी होगा अगर आप समझा सकते हैं कि क्यों और कैसे। सरल हाँ और नहीं बहुत ज्यादा मदद नहीं करते हैं। –

+0

सवाल था "तो, इस विधि के साथ हमें वास्तव में एक म्यूटेक्स लॉक की आवश्यकता नहीं होगी?"तो जवाब हां है (-: कारण यह है कि ऑब्जेक्ट का निर्माण ओएस द्वारा लोडिंग प्रक्रिया का हिस्सा है जो आपके कोड को चलाने से पहले लोड होने की गारंटी देता है। –

+0

प्रश्न में यह कथन भी शामिल है: *" मैं नहीं कर सकता " टी "कैसे" समझते हैं। "* कृपया इसे कुछ जवाब देने के लिए" उत्तर "में अपना कारण दें। –

0

आलसी तत्कालता को हल करने की कोशिश की गई चीज़ों में से एक (न केवल सी ++ संबंधित) static initialization order fiasco था। यह एक समस्या है कि प्रारंभिकरण (एकाधिक अनुवाद इकाइयों के साथ) के क्रम पर आपके पास थोड़ा नियंत्रण नहीं है, लेकिन निर्भरताओं को किसी वस्तु को पहले से मौजूद होने की आवश्यकता हो सकती है, इससे पहले कि दूसरे को बनाया जा सके। आलसी तात्कालिकता के साथ, वस्तु आवश्यकतानुसार बनाई गई है, इसलिए जब तक कोई परिपत्र निर्भरता न हो, तो आपको ठीक होना चाहिए।

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

टिप्पणी है कि:

  • साझा संसाधन अभी भी जब वे पहुंचा जा सकता है बंद कर दिया जाना चाहिए।
  • सी ++ 11 से (और जीसीसी का उपयोग करते समय मुझे अन्य कंपाइलर्स के बारे में निश्चित नहीं है), सबसे आसान समाधान getInstance में स्थिर फ़ंक्शन वैरिएबल का उपयोग करना और उस चर के संदर्भ को वापस करना है। यह थ्रेड-सुरक्षित है।

    class Example 
    { 
        ... 
        static Example& getInstance() 
        { 
        static Example instance; 
        return instance; 
        } 
    };