2015-09-28 8 views
6

एमईएफ स्रोत कोड के माध्यम से ब्राउज़िंग मुझे यह टुकड़ा मिला। क्या कोई बता सकता है कि लॉक के अंदर MemoryBarrier क्यों आवश्यक है?Thread.MemoryBarrier क्यों उपयोग किया जाता है?

पूरे विधि है:

public void SatisfyImportsOnce(ComposablePart part) 
{ 
    this.ThrowIfDisposed(); 

    if (this._importEngine == null) 
    { 
     ImportEngine importEngine = new ImportEngine(this, this._compositionOptions); 

     lock(this._lock) 
     { 
      if (this._importEngine == null) 
      { 
       Thread.MemoryBarrier(); 
       this._importEngine = importEngine; 
       importEngine = null; 
      } 
     } 
     if(importEngine != null) 
     { 
      importEngine.Dispose(); 
     } 
    } 
    this._importEngine.SatisfyImportsOnce(part); 
} 
+0

करने के लिए सौंपा importEngine ताजगी की गारंटी प्रदान करता है यह * लगता है * कि कभी कभी, ताला पर्याप्त –

+0

नहीं है यह एक बहुत अधिक संदर्भ जानने के बिना इस सवाल का जवाब देना असंभव है। –

+3

यह एक कमजोर मेमोरी मॉडल वाले प्रोसेसर पर एफयूडी है, कुछ माइक्रोसॉफ्ट प्रोग्रामर शायद इटेनियम को कम करने से कभी भी ठीक नहीं होंगे। यह सुनिश्चित करता है कि एक और थ्रेड पूरी तरह से निर्मित ऑब्जेक्ट का निरीक्षण कर सकता है जब यह _importEngine संदर्भ का उपयोग करता है। ऑब्जेक्ट फ़ील्ड लिखे जाने से पहले एक कमजोर प्रोसेसर पर संदर्भ स्मृति में लिखा जा सकता है, इसलिए एक और धागा अनियमित फ़ील्ड मान देख सकता है। .NET 2.0 के बाद से जरूरी नहीं है और निश्चित रूप से यहां जरूरी नहीं है क्योंकि लॉक पहले ही मेमोरी बाधा का तात्पर्य है। –

उत्तर

1

Thread.MemoryBarrier कोड अनुकूलन के लिए पुन: क्रम घबराना/संकलक से बचाता है कोई निर्देश।

Treading in C#, by Joe Albahari किताब वह sais में:

  • संकलक, CLR, या CPU दक्षता में सुधार करने के लिए अपने कार्यक्रम के निर्देशों को पुन: व्यवस्थित कर सकते हैं।
  • कंपाइलर, सीएलआर, या सीपीयू कैशिंग ऑप्टिमाइज़ेशन पेश कर सकता है जैसे चर के लिए असाइनमेंट तुरंत अन्य थ्रेडों के लिए दृश्यमान नहीं होंगे।

इस उदाहरण में यह हो सकता है कि importEngine या _importEngine मूल्यों कैश नहीं किया जाता है और यह बहुत महत्वपूर्ण है कि सभी धागे परिवर्तन के बारे में सूचित किए जाने की अभी है।

इसके अलावा MemoryBarrier इस मामले में इससे पहले कि यह _importEngine

+1

लेकिन लॉक भी मेमोरी बैरियर का तात्पर्य है। लॉक के अंदर न तो 'importEngine' और न ही '_importEngine' कैश किया जा सकता है। (जब तक अन्य सामान '_importEngine' पर' this._lock' पर लॉक किए बिना लिखते हैं)। –

+0

@ScottChamberlain आप सही हैं। और यही कारण है कि मुझे लगता है कि इस मामले में मेमोरीबैरियर का उपयोग किया जाता है, अन्य थ्रेड जो _importEnginge को _lock का उपयोग किए बिना लिखते हैं। –

+2

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

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