2010-01-20 10 views
10

मुझे पता है कि .NET मेमोरी मॉडल (.NET Framework पर; कॉम्पैक्ट/माइक्रो/सिल्वरलाइट/मोनो/xna/what-have-you) गारंटी नहीं है कि कुछ प्रकारों (सबसे विशेष रूप से आदिम पूर्णांक और संदर्भ) संचालन की गारंटी थी परमाणु होना.NET मेमोरी मॉडल, अस्थिर चर, और परीक्षण-और-सेट: क्या गारंटी है?

आगे, मेरा मानना ​​है कि x86/x64 परीक्षण-और-सेट निर्देश (और Interlocked.CompareExchange) वास्तव में वैश्विक स्मृति स्थान का संदर्भ देता है, इसलिए यदि यह Interlocked.CompareExchange सफल होता है तो नया मान दिखाई देगा।

अंत में, मुझे विश्वास है कि volatile कीवर्ड संकलक को एक निर्देश का प्रचार करने के पढ़ने & यथाशीघ्र लिखते हैं और इस चर के विषय में संचालन को पुन: व्यवस्थित नहीं है (सही?)।

यह कुछ सवाल की ओर जाता है:

  1. सही ऊपर अपने विश्वासों हैं?
  2. Interlocked.Read में int के लिए अधिभार नहीं है, केवल लंबे समय तक (जो 2 शब्द हैं और इस प्रकार आम तौर पर परमाणु रूप से नहीं पढ़े जाते हैं)। मैंने हमेशा यह माना कि .NET मेमोरी मॉडल ने गारंटी दी है कि नवीनतम मूल्य को इन्सट/संदर्भ पढ़ने के दौरान देखा जाएगा, हालांकि प्रोसेसर कैश, रजिस्टर्स इत्यादि के साथ। मैं यह देखना शुरू कर रहा हूं कि यह संभव नहीं हो सकता है। तो चर को फिर से लाने के लिए मजबूर करने का कोई तरीका है?
  3. पूर्णांक और संदर्भों के लिए उपरोक्त समस्या को हल करने के लिए पर्याप्त अस्थिर है?
  4. 86 पर/x64 मैं मान सकते हैं कि ...

तो देखते हैं दो वैश्विक पूर्णांक चर x और y, दोनों को 0 पर प्रारंभ है कि अगर मैं लिखना:

x = 1; 
y = 2; 

कोई धागा है कि x = 0 और y = 2 देखेंगे (यानी लिखने क्रम में होंगे)। क्या यह अस्थिर है अगर यह बदलता है?

उत्तर

6
  • केवल 32 बिट्स चौड़े (और 64 बिट्स x64 सिस्टम पर चौड़े) पर चर को पढ़ने और लिखने परमाणु हैं। इसका मतलब यह है कि आप int नहीं पढ़ेंगे और आधे लिखित मूल्य प्राप्त करेंगे। इसका मतलब यह नहीं है कि अंकगणित परमाणु है।
  • इंटरलाक्ड ऑपरेशंस मेमोरी बाधाओं के रूप में भी कार्य करता है, इसलिए हाँ, Interlocked.CompareExchange अद्यतन मूल्य देखेंगे।
  • this page देखें। अस्थिर का मतलब आदेश नहीं है। कुछ कंपाइलर अस्थिर चर पर संचालन को पुन: क्रमबद्ध नहीं करना चुन सकते हैं, लेकिन सीपीयू फिर से ऑर्डर करने के लिए स्वतंत्र है। यदि आप सीपीयू को पुन: क्रमबद्ध निर्देशों से रोकना चाहते हैं, तो एक (पूर्ण) मेमोरी बाधा का उपयोग करें।
  • मेमोरी मॉडल यह सुनिश्चित करता है कि पढ़ता है और लिखता है परमाणु है, और अस्थिर कीवर्ड का उपयोग करके यह सुनिश्चित करता है कि हमेशा एक रजिस्टर से नहीं, स्मृति से आ जाएगा। तो आप नवीनतम मान देखेंगे। ऐसा इसलिए है क्योंकि x86 CPUs उचित होने पर कैश को अमान्य कर देंगे - this और this देखें। इसके अलावा, 64-बिट मानों को परमाणु रूप से पढ़ने के लिए InterlockedCompareExchange64 देखें।
  • और अंत में, अंतिम प्रश्न।जवाब वास्तव में x = 0 और y = 2 देख सकता है, और अस्थिर कीवर्ड का उपयोग करने से यह नहीं बदलेगा क्योंकि सीपीयू निर्देशों को फिर से ऑर्डर करने के लिए स्वतंत्र है। आपको स्मृति बाधा की आवश्यकता है।

सारांश:

  1. संकलक मुक्त है फिर से आदेश दिए गए निर्देशों के।
  2. सीपीयू निर्देशों को फिर से आदेश देने के लिए स्वतंत्र है।
  3. वर्ड-साइज्ड पढ़ता है और लिखता परमाणु हैं। अंकगणित और अन्य परिचालन परमाणु नहीं हैं क्योंकि उनमें एक पढ़ना, गणना करना, फिर लिखना शामिल है।
  4. स्मृति से शब्द-आकार का पाठ हमेशा नवीनतम मान प्राप्त करेगा। लेकिन ज्यादातर समय आप नहीं जानते कि क्या आप वास्तव में स्मृति से पढ़ रहे हैं।
  5. एक पूर्ण मेमोरी बाधा बंद हो जाती है (1) और (2)। अधिकांश कंपाइलर्स आपको स्वयं (1) को रोकने की अनुमति देते हैं।
  6. अस्थिर कीवर्ड सुनिश्चित करता है कि आप स्मृति से पढ़ रहे हैं - (4)।
  7. इंटरलाक्ड ऑपरेशंस (लॉक उपसर्ग) कई परिचालनों को परमाणु होने की अनुमति देता है। उदाहरण के लिए, एक पढ़ें + लिखें (इंटरलाक्ड एक्सचेंज)। या एक पढ़ें + तुलना + लिखें (InterlockedCompareExchange)। वे मेमोरी बाधाओं के रूप में भी कार्य करते हैं, इसलिए (1) और (2) बंद हो जाते हैं। वे हमेशा स्मृति (स्पष्ट रूप से) लिखते हैं, इसलिए (4) सुनिश्चित किया जाता है।
+2

.NET के बारे में कुछ में "सी कीवर्ड मिथ्स डिस्पेल" से जुड़ने में समस्या यह है कि 'अस्थिर' के बारे में मिथकों का एक प्रमुख स्रोत यह है कि लोग सी, सी # और जावा में समान हैं। सी # 'अस्थिरता में वास्तव में http://msdn.microsoft.com/en-us/library/aa645755%28v=VS.71%29.aspx के अनुसार कुछ ऑर्डरिंग अर्थशास्त्र है। –

+0

"धागा वास्तव में x = 0 और y = 2 देख सकता है" - चूंकि .NET 2.0 लिखने के संचालन को पुन: व्यवस्थित नहीं किया जा सकता है। – Vlad

0

नहीं, अस्थिर कीवर्ड और परमाणु गारंटी बहुत कमजोर है। यह सुनिश्चित करने के लिए आपको स्मृति बाधा की आवश्यकता है। आप थ्रेड के साथ स्पष्ट रूप से एक प्राप्त कर सकते हैं। MemoryBarrier() विधि।

+0

ठीक है ... वह 2 और 3 का जवाब देता है, लेकिन # 4 के बारे में क्या है (ऑर्डर जिसमें थ्रेड डेटा देखेंगे)? –

+0

इसके अलावा: http://msdn.microsoft.com/en-us/library/x13ttww7%28VS.71%29.aspx (lol msdn urls): "सिस्टम हमेशा बिंदु पर एक अस्थिर वस्तु के वर्तमान मान को पढ़ता है यह अनुरोध किया जाता है, भले ही पिछले निर्देश ने उसी ऑब्जेक्ट से किसी मान के लिए पूछा हो। इसके अलावा, ऑब्जेक्ट का मान तुरंत असाइनमेंट पर लिखा जाता है। अस्थिर संशोधक आमतौर पर उस फ़ील्ड के लिए उपयोग किया जाता है जिसे लॉक का उपयोग किए बिना एकाधिक थ्रेड द्वारा एक्सेस किया जाता है पहुंच को क्रमबद्ध करने के लिए कथन। अस्थिर संशोधक का उपयोग सुनिश्चित करता है कि एक थ्रेड किसी अन्य थ्रेड द्वारा लिखे गए सबसे अद्यतित मान को पुनर्प्राप्त करता है। " –

+0

ओह और नमूना कोड http://msdn.microsoft में।com/en-us/लाइब्रेरी/aa645755% 28VS.71% 29.aspx - ऐसा लगता है कि आपका उत्तर विरोधाभास है। –

2

इस पुराने धागे में आया था। volatile के संबंध में भाग को छोड़कर हंस और wj32 के उत्तर सभी सही हैं।

विशेष रूप से अपने प्रश्न

86 पर के बारे में/x64 मैं मान सकते हैं कि ... अगर वहाँ दो वैश्विक पूर्णांक चर x और y कर रहे हैं, दोनों को 0 पर प्रारंभ है कि अगर मैं लिखने: x = 1; y = 2;

कि कोई थ्रेड x = 0 और y = 2 (यानी लिखने क्रम में होंगे) देखेंगे। क्या में यह परिवर्तन अस्थिर है?

तो y अस्थिर है, x को लिखने गारंटी y को लिखने से पहले होने की, इसलिए कोई धागा कभी x = 0 और y = 2 देखेंगे। इसका कारण यह है कि एक अस्थिर चर के लिए लिखने में "रिलीज अर्थात्" (तार्किक रूप से रिलीज बाड़ के उत्सर्जन के बराबर) होता है, यानी सभी पढ़ने/लिखने के निर्देशों से पहले इसे पास नहीं किया जाएगा। (इसका तात्पर्य है कि यदि एक्स अस्थिर है लेकिन y नहीं है, तो भी आप अप्रत्याशित x = 0 और y = 2 देख सकते हैं।) अधिक जानकारी के लिए & कोड उदाहरण C# spec में देखें।

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