2012-04-27 17 views
8

मैं एक वर्ग है:स्थैतिक विधि थ्रेड-सुरक्षित से संदर्भ लौटा रहा है?

class PrintStringDataBuilder 
{ 
    PrintStringDataBuilder() { } 
    public static GetInstance() 
    { 
     return new PrintStringDataBuilder(); 
    } 

    //other class methods and fields, properties 
} 

के रूप में ग्राहक कोड से एक्सेस किया गया:

PrintStringDataBuilder instance = PrintStringDataBuilder.GetInstance(); 

कॉल धागा सुरक्षित ऊपर है?

संपादित करें: बस PrintStringDataBuilder बिल्डर = नए PrintStringDataBuilder लेखन से बचने के लिए() की कोशिश कर रहा; एएसपीएनटी एमवीसी वेब ऐप में कई बार। PrintStringDataBuilder क्लास में कोई अन्य स्थैतिक विधियां, स्थैतिक फ़ील्ड या स्थैतिक गुण नहीं हैं।

+0

यह वास्तव में क्या 'नई PrintStringDataBuilder पर निर्भर करता है()' करता है। क्या आप इसे सिंगलटन बनाने की कोशिश कर रहे हैं? यदि ऐसा है, तो यह ऐसा नहीं कर रहा है। यदि नहीं, तो आपके पास एक स्थिर 'GetInstance()' विधि क्यों है जब आप केवल कन्स्ट्रक्टर को कॉल कर सकते हैं। – cadrell0

+0

क्या आपके पास निजी कन्स्ट्रक्टर 'प्रिंटस्ट्रिंगडाटाबिल्डर' है, आप अन्य फ़ील्ड कैसे प्रारंभ कर रहे हैं? –

+0

डाउन-वोट क्यों? मुझे लगता है कि यह एक अच्छा सवाल है – n8wrl

उत्तर

11

हां? उस वर्ग के निर्माता के आंतरिक जानने के बिना, आप कह सकते हैं कि GetInstance() पर कॉल करना सुरक्षित था। उस उदाहरण पर किसी भी तरीके को थ्रेड सुरक्षित होने की गारंटी नहीं दी जाएगी, खासकर जब से आपने उन तरीकों में से कोई भी प्रस्तुत नहीं किया है।

यह केवल फैक्ट्री पैटर्न के रूप में जाना जाता है।

संपादित करें: यदि आप एक सिंगलटन वापस जाने के लिए कोशिश कर रहे हैं, तो आप यह इतना की तरह कर सकते हैं:

नेट 4+

private static Lazy<PrintStringDataBuilder> _instance = new Lazy<PrintStringDataBuilder>(() => 
    { 
     return new PrintStringDataBuilder(); 
    }); 

public static PrintStringDataBuilder GetInstance() 
{ 
    return _instance.Value; 
} 

.NET 3.5 और नीचे

private static PrintStringDataBuilder _instance = null; 
private static object _lockObject = new object(); 

public static PrintStringDataBuilder GetInstance() 
{ 
    if(_instance == null) 
    { 
     lock(_lockObject) 
     { 
       if(_instance == null) 
       _instance = new PrintStringDataBuilder(); 
     } 
    } 

    return _instance; 
} 
+0

क्षमा करें, कन्स्ट्रक्टर लिखना भूल गए। मैंने कोड अपडेट किया। – mxasim

+0

हां, कन्स्ट्रक्टर थ्रेड सुरक्षित है (यह कुछ भी नहीं करता है)। क्या आप एक सिंगलटन वापस करने की कोशिश कर रहे हैं? – Tejs

+0

नहीं, बस प्रिंटस्ट्रिंगडेटाबिल्डर बिल्डर लिखने से बचने की कोशिश कर रहा है = नया प्रिंटस्ट्रिंगडेटाइल्डर(); कई बार – mxasim

5

तक 'थ्रेडसेफ' क्या आप चिंतित हैं कि आपकी स्थिर विधि को कॉल करने वाले कई थ्रेड समान प्रिंटस्ट्रिंगडेटाइल्डर प्राप्त करने जा रहे हैं? इसका उत्तर नहीं है, और कॉल थ्रेड-सुरक्षित है।

ऐसा कहकर, कोई भी छोटे स्निपेट से नहीं बता सकता है कि आप बाकी वर्ग या उसके कन्स्ट्रक्टर हैं या नहीं। क्लास इंस्टेंस थ्रेड-सुरक्षित नहीं होने के कई कारण हैं। यदि वे लॉकिंग के बिना स्थैतिक गुणों का संदर्भ देते हैं तो एक उदाहरण है।

3

एक विधि दर्ज करना हमेशा थ्रेड सुरक्षित होता है। साझा डेटा तक पहुंच नहीं हो सकती है। तो यह कोड थ्रेड सुरक्षित है क्योंकि साझा डेटा नहीं है।

यदि आपका इरादा सभी धागे के लिए PrintStringDataBuilder का एक उदाहरण है तो उस उद्देश्य के लिए आपका कोड काम नहीं करेगा। आपको उचित सिंगलटन की आवश्यकता है। नेट 4 में कोड बहुत कॉम्पैक्ट हो सकता है:

private static Lazy<PrintStringDataBuilder> instance = new Lazy<PrintStringDataBuilder>(); 

public static PrintStringDataBuilder Instance 
{ 
    get { return instance.Value; } 
} 

यह गारंटी है कि हर धागा PrintStringDataBuilder.Instance में एक ही है और केवल एक है जो एक आलसी तरीके से बनाया जाएगा अपने PrintStringDataBuilder वस्तु का उदाहरण को इंगित करेगा यानी केवल जब यह पहले इस्तेमाल किया जाता है और जल्द ही नहीं।

1

@Tejs,

वास्तव में, .NET में आप दोबारा जांच ताला तंत्र का उपयोग करने की जरूरत नहीं है - वहाँ उसके चारों ओर बेहतर तरीके हैं। लेकिन यदि आप ऐसा करना चुनते हैं, तो डबल-चेक लॉक का कार्यान्वयन गलत है और वास्तव में थ्रेड-सुरक्षित नहीं है। संकलक _instance = new PrintStringDataBuilder(); का आरंभीकरण दूर का अनुकूलन कर सकते हैं - आपकी उदाहरण वास्तव में धागे की सुरक्षित बनाने के लिए 3 संभव संशोधनों हैं: - निश्चित रूप से सबसे आसान

  1. स्थिर सदस्य इनलाइन प्रारंभ!
private static PrintStringDataBuilder _instance = new PrintStringDataBuilder; 
    public static PrintStringDataBuilder GetInstance() 
    { 
     return _instance; 
    } 

2। यह सुनिश्चित करने के लिए 'अस्थिर' कीवर्ड का उपयोग करें कि PrintStringDataBuilder की शुरुआत जेआईटी द्वारा अनुकूलित नहीं है।


private static volatile PrintStringDataBuilder _instance = null; 
private static object _lockObject = new object(); 

public static PrintStringDataBuilder GetInstance() 
{ 
    if(_instance == null) 
    { 
     lock(_lockObject) 
     { 
       if(_instance == null) 
       { 
       _instance = new PrintStringDataBuilder(); 
       } 
     } 
    } 

    return _instance; 
}

3। दोबारा जांच लॉक के साथ Interlocked.Exchange का उपयोग करें:


private static PrintStringDataBuilder _instance = null; 
private static object _lockObject = new object(); 

public static PrintStringDataBuilder GetInstance() 
{ 
    if(_instance == null) 
    { 
     lock(_lockObject) 
     { 
       if(_instance == null) 
       { 
       var temp = new PrintStringDataBuilder(); 
       Interlocked.Exchange(ref _instance, temp); 
       } 
     } 
    } 

    return _instance; 
}

आशा इस मदद करता है।

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