2010-11-23 13 views
6

मैं सी # में निम्नलिखित की तरह कुछ है:,नेट धागा सुरक्षित कैश्ड परिणाम

private double _x; 
private bool _xCalculated; 

private double GetX() { 
    if (!_xCalculated) { 
     _x = ... // some relatively expensive calculation 
     _xCalculated = true; 
    } 

    return _x; 
} 

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

क्या यह मेरी सही समझ है?

उत्तर

6

कुछ टिप्पणियों:

  1. डबल में दुकान परमाणु नहीं हो सकता है
  2. bool करने के लिए लिखने कोई पुनर्व्यवस्था होता है कोड
  3. 01,235,164 काम करना चाहिए परमाणु
  4. CPU वास्तुकला स्मृति संचालन पर निर्भर करता है
  5. पुनर्क्रमित किया जा सकता है किया जाना चाहिए

जबकि मुझे लगता है कि x86 memory ordering guarantees यह सुरक्षित बनाओ मैं इसके बारे में पूरी तरह से निश्चित नहीं हूं। X86 की गारंटी को मेल करने के लिए हाल ही में .NET की स्मृति आदेश गारंटी को मजबूत किया गया है (मुझे लगता है कि .NET 4 में)।

Memory Model in .net
More on memory ordering
यह कहा गया है कि दुकानों .net जो मुझे लगता है कि में पुनर्क्रमित नहीं कर रहे हैं मतलब है कि आपके कोड सुरक्षित है। लेकिन लॉकलेस प्रोग्रामिंग कठिन है, इसलिए मैं कुछ सूक्ष्म मुद्दों को देख सकता हूं। शायद अगर खंड में पढ़ा समस्या पैदा कर सकता है।

मैं इस कोड का उपयोग न करने की सलाह देता हूं जबतक कि आप थ्रेडिंग विशेषज्ञ नहीं हैं और वास्तव में वास्तव में प्रदर्शन की आवश्यकता है। अन्यथा ताले की तरह कुछ और स्पष्ट उपयोग करें। ताले उस महंगे नहीं हैं अगर उनका विरोध नहीं किया जाता है।

+1

। क्यों लगता है कि हार्डवेयर एक्स कैसे काम कर सकता है, जब कोई लॉक सरल, स्पष्ट, गारंटीकृत नहीं है और प्रदर्शन अंतर के बारे में बात करने योग्य नहीं है, तो हार्डवेयर एक्स कैसे काम कर सकता है? – smirkingman

+0

मैं अपने उद्देश्यों के लिए सर्वोत्तम कार्यान्वयन खोजने के लिए प्रदर्शन परीक्षण कर रहा हूं, लेकिन मैं जानना चाहता था कि यह समाधान शुरू करने के लिए मान्य है या नहीं। – derkyjadex

+0

आपके समाधान के साथ समस्या यह है कि यह जानना बहुत मुश्किल है कि यह सही है या नहीं। और चूंकि थ्रेडिंग मुद्दे गैर निर्धारक हैं, इसलिए आप इसका परीक्षण भी नहीं कर सकते हैं। – CodesInChaos

2

यह थ्रेड-सुरक्षित नहीं है। और हाँ, आपकी समझ सही है। आप इसे थ्रेड-सुरक्षित बनाने के लिए lock() कथन का उपयोग कर सकते हैं।

http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.71).aspx

private object objLock = new object(); 
private double GetX() { 
    lock(objLock) { 
     if (!_xCalculated) { 
      _x = ... // some relatively expensive calculation 
      _xCalculated = true; 
     } 
    } 
    return _x; 
} 
+2

कृपया लॉक (यह) का उपयोग करने से बचें। एक निजी ऑब्जेक्ट लॉकऑबजेक्ट = नई ऑब्जेक्ट() पर लॉक करना बेहतर है; देखें http://www.toolazy.me.uk/template.php?content=lock(this)_causes_deadlocks.xml –

+0

और यह बताते हुए कि यह सुरक्षित नहीं है, उस दावे के कुछ कारण दिए बिना एक बोल्ड दावा है। – CodesInChaos

+0

ठीक है, लॉक (यह) एक quickshot था। लेकिन यह निश्चित रूप से थ्रेड सुरक्षित नहीं है: _x = ... कम से कम एक ऑपरेशन है। _xCalculated = सत्य इसके बाद दूसरे ऑपरेशन के रूप में अनुसरण करता है, इसलिए दौड़ की स्थिति हो सकती है। – Hinek

1

यह मंच पर निर्भर करता है, मुझे नहीं लगता कि यह अपनी कल्पना के अनुसार नेट स्मृति मॉडल के साथ सुरक्षित है, लेकिन मुझे लगता है कि वर्तमान Microsoft CLR पर ठीक है। मुद्दा यह है कि सीपीयू को रीडर मेमोरी लिखने की अनुमति है।

कर सकते हैं किसी कृपया कल्पना करने के लिए विस्तृत लिंक के साथ आ ...

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