22
private volatile static Singleton uniqueInstance 

सिंक्रनाइज़ेशन के लिए डबल लॉक विधि का उपयोग करते समय एक सिंगलटन में एकल उदाहरण को अस्थिर घोषित क्यों किया जाता है? क्या मैं इसे समान अस्थिर घोषित किए बिना समान कार्यक्षमता प्राप्त कर सकता हूं?डबल लॉक का उपयोग करते समय सिंगलटन इंस्टेंस अस्थिर बनाने का क्या मतलब है?

+0

संबंधित पोस्ट [यहां] (https : //stackoverflow.com/q/18093735/465053) और [यहां] (https://stackoverflow.com/q/12316406/465053) क्यों पहली जगह में डबल चेकिंग की आवश्यकता है। विकिपीडिया – RBT

उत्तर

19

volatile के बिना कोड एकाधिक धागे के साथ सही ढंग से काम नहीं करता है।

विकिपीडिया के Double-checked locking से:

J2SE 5.0 के रूप में, इस समस्या को तय किया गया है। अस्थिर कीवर्ड अब सुनिश्चित करता है कि एकाधिक थ्रेड सिंगलटन इंस्टेंस को सही तरीके से संभालते हैं। यह नया मुहावरा The "Double-Checked Locking is Broken" Declaration में वर्णित है:

// Works with acquire/release semantics for volatile 
// Broken under Java 1.4 and earlier semantics for volatile 
class Foo { 
    private volatile Helper helper = null; 
    public Helper getHelper() { 
     Helper result = helper; 
     if (result == null) { 
      synchronized(this) { 
       result = helper; 
       if (result == null) { 
        helper = result = new Helper(); 
       } 
      } 
     } 
     return result; 
    } 

    // other functions and members... 
} 

सामान्य तौर पर आप यदि संभव हो तो ताला लगा दोबारा जांच से बचना चाहिए, के रूप में यह सही पाने के लिए मुश्किल है और यह त्रुटि खोजने के लिए मुश्किल हो सकता है यदि आप गलत समझ गया । बजाय इस सरल तरीका का प्रयास करें:

तो सहायक ऑब्जेक्ट स्थिर है (कक्षा लोडर प्रति एक), एक वैकल्पिक initialization on demand holder idiom

// Correct lazy initialization in Java 
@ThreadSafe 
class Foo { 
    private static class HelperHolder { 
     public static Helper helper = new Helper(); 
    } 

    public static Helper getHelper() { 
     return HelperHolder.helper; 
    } 
} 
+0

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

+2

के लिए – Xtroce

+0

से बचना चाहिए धारक मुहावरे के मामले में आप कन्स्ट्रक्टर को तर्क कैसे पारित करेंगे? –

35

volatile स्मृति से फिर से आदेश दिया जा रहा लिखते रोकता है, सिंगलटन के पॉइंटर के माध्यम से आपके सिंगलटन के अनियमित क्षेत्रों को पढ़ने के लिए अन्य धागे के लिए असंभव बनाना।

इस स्थिति पर विचार करें: थ्रेड ए uniqueInstance == null, ताले की खोज करता है, यह पुष्टि करता है कि यह अभी भी null है, और सिंगलटन के कन्स्ट्रक्टर को कॉल करता है। कन्स्ट्रक्टर सिंगलटन के अंदर सदस्य XYZ में लिखता है, और रिटर्न देता है। थ्रेड ए अब नव निर्मित सिंगलटन के संदर्भ को uniqueInstance में संदर्भित करता है, और इसके लॉक को रिलीज़ करने के लिए तैयार हो जाता है।

जैसे ही थ्रेड ए लॉक को रिलीज़ करने के लिए तैयार हो जाता है, थ्रेड बी साथ आता है, और पता चलता है कि uniqueInstancenull नहीं है। थ्रेड BuniqueInstance.XYZ तक पहुंचता है यह सोच रहा है कि इसे प्रारंभ किया गया है, लेकिन क्योंकि सीपीयू ने फिर से लिखा है, इसलिए डेटा XYZ में लिखा गया डेटा थ्रेड बी के लिए दृश्यमान नहीं किया गया है। इसलिए, थ्रेड बी XYZ के अंदर एक गलत मान देखता है, जो कि है गलत।

जब आप uniqueInstance अस्थिर चिह्नित करते हैं, तो मेमोरी बाrier डाला जाता है। uniqueInstance से पहले शुरू किए गए सभी लेखन uniqueInstance से पहले संशोधित किया जाएगा, ऊपर वर्णित पुनरावृत्ति स्थिति को रोकना।

+1

उत्तर –

+0

के लिए धन्यवाद विशिष्ट होने के लिए, दो पुनर्वित्तित लिखते हैं: 1) ए 'अद्वितीय इंस्टेंस' और 2) के लिए मेमोरी पता असाइन करता है, 'XYZ' कुछ सार्थक हो जाता है। – lcn

+0

@dasblinkenlight: आपने कहा है कि "क्योंकि सीपीयू ने फिर से लिखा है ...."। कृपया बताएं कि रीडरिंग लिखने का मतलब क्या है? –

7

डबल लॉक का उपयोग कर से बचने के लिए, या अस्थिर मैं पालन

enum Singleton { 
    INSTANCE; 
} 

उदाहरण बनाना उपयोग करते हैं, सरल आलसी लोड होने और सुरक्षित थ्रेड।

0

किसी अस्थिर क्षेत्र को लिखें किसी भी पढ़ने के ऑपरेशन से पहले होगा। नीचे बेहतर समझ के लिए एक उदाहरण कोड है:

private static volatile ResourceService resourceInstance; 
//lazy Initialiaztion 
public static ResourceService getInstance() { 
    if (resourceInstance == null) { // first check 
     synchronized(ResourceService.class) { 
      if (resourceInstance == null) { // double check 
       // creating instance of ResourceService for only one time 
       resourceInstance = new ResourceService();      
      } 
     } 
    } 
    return resourceInstance; 
} 

इस लिंक से आपको बेहतर सेवा कर सकते हैं http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html

1

आप फॉलो कोड का उपयोग कर सकते हैं:

private static Singleton uniqueInstance; 

public static synchronized Singleton getInstance(){ 
    if(uniqueInstance == null){ 
     uniqueInstance = new Singleton(); 
    } 
    return uniqueInstance 
}