2010-05-16 11 views
12

मैंने हाल ही में मेमोरी बाधाओं और रीडरिंग मुद्दे के बारे में पढ़ा है और अब मुझे इसके बारे में कुछ भ्रम है।लॉक स्टेटमेंट द्वारा मेमोरी बैरियर

इस परिदृश्य पर विचार करें:

private object _object1 = null;  
private object _object2 = null; 
private bool _usingObject1 = false; 

private object MyObject 
{ 
    get 
    { 
     if (_usingObject1) 
     { 
      return _object1; 
     } 
     else 
     { 
      return _object2; 
     } 
    } 
    set 
    { 
     if (_usingObject1) 
     { 
      _object1 = value; 
     } 
     else 
     { 
      _object2 = value; 
     } 
    } 
} 

private void Update() 
{ 
    _usingMethod1 = true; 
    SomeProperty = FooMethod(); 
    //.. 
    _usingMethod1 = false; 
} 
  1. Update विधि पर; _usingMethod1 = true कथन हमेशा संपत्ति प्राप्त करने या स्थापित करने से पहले निष्पादित किया गया है? या पुनर्निर्देशन के मुद्दे के कारण हम इसकी गारंटी नहीं दे सकते?

  2. हम जैसे

    private volatile bool _usingMethod1 = false; 
    
  3. volatile का उपयोग करते हैं हम lock; का उपयोग करना चाहिए हम तो गारंटी ले सकते हैं ताला भीतर हर बयान की तरह क्रम में निष्पादित किया जाएगा:

    private void FooMethod() 
    { 
        object locker = new object(); 
        lock (locker) 
        { 
         x = 1; 
         y = a; 
         i++; 
        } 
    } 
    

उत्तर

28

मेमोरी बाधाओं का विषय काफी जटिल है। यह समय-समय पर विशेषज्ञों की भी यात्रा करता है। जब हम एक स्मृति बाधा के बारे में बात करते हैं तो हम वास्तव में दो अलग-अलग विचारों को जोड़ते हैं।

  • मोल बाड़: एक स्मृति बाधा है, जिसमें अन्य & राईट पढ़ता बाड़ से पहले स्थानांतरित करने के लिए अनुमति नहीं है।
  • रिलीज बाड़: एक मेमोरी बाधा जिसमें & लिखते हैं बाड़ के बाद स्थानांतरित करने की अनुमति नहीं है।

एक स्मृति बाधा है कि बनाता है केवल दो में से एक कभी कभी एक आधा बाड़ कहा जाता है। एक मेमोरी बाधा जो दोनों बनाता है उसे कभी-कभी पूर्ण-बाड़ कहा जाता है।

volatile कीवर्ड आधा बाड़ बनाता है। अस्थिर क्षेत्रों के पढ़ने ने अर्थशास्त्र प्राप्त किया है जबकि लिखने से अर्थशास्त्र जारी किया गया है। इसका मतलब है कि पढ़ने या लिखने से पहले कोई निर्देश नहीं ले जाया जा सकता है।

lock कीवर्ड दोनों सीमाओं (प्रवेश और निकास) पर पूर्ण-बाड़ बनाता है। इसका मतलब है कि प्रत्येक सीमा के पहले या बाद में कोई भी निर्देश स्थानांतरित नहीं किया जा सकता है।

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

तो आपके सवालों के जवाब:

  1. किसी एकल थ्रेड के दृष्टिकोण से ... हाँ। एक और थ्रेड के परिप्रेक्ष्य से ... नहीं।

  2. यह निर्भर करता है। यह काम कर सकता है, लेकिन मुझे यह समझने की ज़रूरत है कि आप क्या करने की कोशिश कर रहे हैं।

  3. किसी अन्य थ्रेड के परिप्रेक्ष्य से ... नहीं। पढ़ना और लिखना ताला की सीमाओं के भीतर घूमने के लिए स्वतंत्र हैं। वे सिर्फ उन सीमाओं के बाहर नहीं जा सकते हैं। यही कारण है कि अन्य धागे के लिए मेमोरी बाधाएं भी बनाना महत्वपूर्ण है।

+0

जानकारी के लिए धन्यवाद, यह वास्तव में मुझे अवधारणा को और समझने में मदद करता है .. मुझे यह सुनिश्चित करने के लिए क्या करना है कि "_usingMethod1 = true" निर्देश अगले निर्देश से पहले किया जाएगा कुछप्रॉपर्टी = FooMethod(); मल्टीथ्रेड सेनारियो में इसे कैसे लागू किया जाए? द्वारा: _usingMethod1 = सत्य; Thread.MemoryBarrier(); कुछ प्रॉपर्टी = FooMethod(); या पूर्ण बाड़ के लिए लॉक करें ताकि कोई पुन: व्यवस्थित न हो: लॉक (लॉकर) {_usingMethod1 = true; } कुछ प्रॉपर्टी = FooMethod(); या शायद _usingMethod1 को एक अस्थिर चर बनाकर। आपकी सहायता के लिए धन्यवाद. –

+2

मैं अद्यतन विधि की संपूर्ण सामग्री को लॉक में लपेटूंगा। मेमोरी बाधाओं के अतिरिक्त यह ग्रेनटेस परमाणुता भी है, जो समान रूप से महत्वपूर्ण है। इसके अलावा, इन लॉक-फ्री मुहावरे (अस्थिर, थ्रेड। मेमरीबैरियर, आदि के माध्यम से) सही होने के लिए अविश्वसनीय रूप से कठिन हैं। –

4

अस्थिर कीवर्ड यहां कुछ भी पूरा नहीं करता है। इसकी बहुत कमजोर गारंटी है, यह स्मृति बाधा का मतलब नहीं है। आपका कोड कोई अन्य थ्रेड बनने वाला नहीं दिखाता है, इसलिए लॉकिंग की आवश्यकता होने पर अनुमान लगाना मुश्किल है। हालांकि यह एक कठिन आवश्यकता है यदि दो धागे एक ही समय में अद्यतन() को निष्पादित कर सकते हैं और उसी ऑब्जेक्ट का उपयोग कर सकते हैं।

सावधान रहें कि पोस्ट के रूप में आपका लॉक कोड कुछ भी लॉक नहीं करता है। प्रत्येक धागे का "लॉकर" ऑब्जेक्ट का अपना उदाहरण होगा। आपको इसे अपने वर्ग का एक निजी क्षेत्र बनाना है, जिसे निर्माता या प्रारंभकर्ता द्वारा बनाया गया है। इस प्रकार:

private object locker = new object(); 

private void Update() 
{ 
    lock (locker) 
    { 
     _usingMethod1 = true; 
     SomeProperty = FooMethod(); 
     //.. 
     _usingMethod1 = false; 
    } 
} 

ध्यान दें कि कुछ प्रॉपर्टी असाइनमेंट पर भी दौड़ होगी।

+0

अस्थिरता में स्मृति बाधा है; और इसलिए मैंने पूछा कि क्या उसके साथ उस मोटाई बाधा को पुन: व्यवस्थित करना होगा ताकि _usingMethod1 = सत्य हमेशा संपत्ति प्राप्त करने या स्थापित करने से पहले उत्साहित हो सके। कुछ प्रॉपर्टी, मैं सिमोन्रनाइज़ेशन समस्या के लिए अन्य धागे के साथ याद रखने के लिए केवल लॉक प्रदान करता हूं और इसलिए मैं इसे उद्देश्य के भीतर विधि के भीतर एक स्थानीय चर बना देता हूं क्योंकि मैं पूछ रहा था कि क्या यह ताला के अंदर निर्देशों की पुनरावृत्ति से बच जाएगा। –

+1

एक एकल धागा * हमेशा * इसका उपयोग करने वाले चर के निरंतर दृश्य है। यदि कार्यक्रम नहीं था तो प्रोग्राम काम नहीं कर सके। –

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