2009-02-05 19 views
9

मैं उलझन में हूं। मेरे previous question के उत्तर मेरी धारणाओं की पुष्टि करने लगते हैं। लेकिन जैसा कि कहा गया है here अस्थिरता नेट पर परमाणु को आश्वस्त करने के लिए पर्याप्त नहीं है। एमएसआईएल में वृद्धि और असाइनमेंट जैसे ऑपरेशन का अनुवाद सीधे एकल, देशी ओपेकोडे या कई सीपीयू में नहीं किया जाता है, साथ ही साथ उसी रैम स्थान पर पढ़ और लिख सकते हैं।क्यों अस्थिर पर्याप्त नहीं है?

स्पष्ट करने के लिए:

  1. मैं लिखता है जानना चाहता हूँ और पढ़ने से अधिक CPU पर परमाणु कर रहे हैं?
  2. मैं समझता हूं कि अस्थिर क्या है। लेकिन क्या यह पर्याप्त है? क्या मुझे इंटरलॉक ऑपरेशंस का उपयोग करने की ज़रूरत है यदि मैं अन्य सीपीयू द्वारा नवीनतम मूल्य लिखना चाहता हूं?

उत्तर

10

हर्ब सटर ने हाल ही में volatile पर एक लेख लिखा और मूल सी ++ में इसका वास्तव में क्या मतलब है (यह स्मृति पहुंच और परमाणुता के क्रम को कैसे प्रभावित करता है)। .NET, और जावा वातावरण।

+3

यह * एक बहुत अच्छा पढ़ा गया है (और निश्चित रूप से एक +1 का हकदार है), लेकिन इसे सामान्य रूप से एसओ उत्तरों के लिए कुछ हद तक स्वयं निहित होने के लिए प्राथमिकता दी जाती है। यह अच्छा होगा अगर आपके उत्तर में उस आलेख के महत्वपूर्ण हिस्सों का सारांश शामिल है, तो बस (1) पृष्ठ को स्किम करने वाले लोग इसे देखेंगे, और (2) इसलिए लेख को स्थानांतरित या हटाए जाने पर उत्तर प्रासंगिक रहता है। – jalf

-1

वोल्टाइल एक कंपाइलर कीवर्ड है जो संकलक को बताता है कि क्या करना है। यह अनिवार्य रूप से (अनिवार्य रूप से) बस संचालन में अनुवाद नहीं करता है जो परमाणुता के लिए आवश्यक है। यह आमतौर पर ऑपरेटिंग सिस्टम तक छोड़ दिया जाता है।

संपादित करें: स्पष्टीकरण के लिए, अगर आप परमाणुता की गारंटी देना चाहते हैं तो अस्थिर कभी पर्याप्त नहीं होता है। या इसके बजाय, यह पर्याप्त बनाने के लिए संकलक पर निर्भर है या नहीं।

+0

डुह। लेकिन वृद्धि और असाइनमेंट के बारे में क्या? –

+0

यदि आप इंटरलाक्ड ऑपरेशंस के बारे में बात कर रहे हैं, यानी, परमाणु संचालन की गारंटी है, तो उन दोनों को बस संचालन (x86 लॉक ऑपोड मोडिफायर का उपयोग करता है) या ओएस (पीपीसी को समकक्ष करने के लिए lwarx/stwrx का उपयोग करने की आवश्यकता है) द्वारा लागू किया जाना चाहिए। – MSN

+0

परमाणुता के लिए बस ऑपरेशन की आवश्यकता क्यों होगी विशेष रूप से यदि आपका सीपीयू Core2Duo में से एक है? और ओएस तक छोड़ दिया? तुम मज़ाक कर रहे हो! –

6

.NET में अस्थिर चर चरम परमाणु तक पहुंच बनाता है।

समस्या यह है कि अक्सर पर्याप्त नहीं होता है। क्या होगा यदि आपको चर को पढ़ने की आवश्यकता है, और यदि यह 0 है (यह दर्शाता है कि संसाधन मुक्त है), तो आप इसे 1 पर सेट करते हैं (यह दर्शाता है कि यह लॉक है, और अन्य धागे इसे से दूर रहना चाहिए)।

0 पढ़ना परमाणु है। 1 लिखना परमाणु है। लेकिन उन दो परिचालनों के बीच, कुछ भी हो सकता है। तुम एक 0 पढ़ सकता है, और फिर इससे पहले कि आप 1 लिख सकते हैं, एक और धागा में कूदता है, 0 पढ़ता है, और नेट में अस्थिर एक 1.

लिखते हैं हालांकि, चर करने के लिए पहुंच की गारंटी atomicity करता है। यह केवल एकाधिक पहुंच पर निर्भर संचालन के लिए थ्रेड सुरक्षा की गारंटी नहीं देता है। (अस्वीकरण: सी/सी ++ में अस्थिरता भी इसकी गारंटी नहीं देता है। बस इतना आप जानते हैं। यह बहुत कमजोर है, और कभी-कभी बग का स्रोत होता है क्योंकि लोग मानते हैं कि यह परमाणुता की गारंटी देता है :))

तो आपको ताले का उपयोग करने की आवश्यकता है अच्छी तरह से, एक थ्रेड-सुरक्षित खंड के रूप में कई संचालन को एक साथ समूहित करने के लिए। (या, सरल संचालन के लिए, Interlocked .NET में ऑपरेशन चाल कर सकते हैं)

+0

ध्यान दें, यह अस्थिर नहीं है जो चर के लिए परमाणुता की गारंटी देता है - यह दूसरी तरफ है: यदि एक चर को परमाणु रूप से पहुंचा जा सकता है, तो 'अस्थिर' इसे लागू किया जा सकता है। – xxbbcc

0

आपका प्रश्न पूरी तरह से समझ में नहीं आता है, क्योंकि volatile specifies the how the read happens, बहु-चरण प्रक्रियाओं परमाणुता नहीं है। मेरी कार मेरे लॉन को नहीं उड़ाती है, लेकिन मैं इसके खिलाफ इसे पकड़ने की कोशिश नहीं करता हूं। :)

0

समस्या आपके चर के मूल्यों की पंजीकृत आधारित कैश की गई प्रतियों के साथ आता है।

कोई मान पढ़ने पर, सीपीयू पहली बार मुख्य स्मृति (धीमी) की जांच करने से पहले एक रजिस्टर (तेज़) में होगा या नहीं।

वोल्टाइल संकलक को मुख्य मेमोरी असप में मूल्य को धक्का देने के लिए कहता है, और कैश किए गए रजिस्टर मान पर भरोसा नहीं करता है। यह केवल कुछ मामलों में उपयोगी है।

यदि आप सिंगल ऑप कोड लिख रहे हैं, तो आपको इंटरलाक्ड.इंटरमेंट से संबंधित तरीकों का उपयोग करना होगा .. लेकिन वे एक सुरक्षित सुरक्षा में क्या कर सकते हैं में काफी सीमित हैं।

सुरक्षित और सबसे विश्वसनीय शर्त लॉक() (यदि आप इंटरलाक्ड नहीं कर सकते हैं।*)

संपादित करें: लिखने और पढ़ना परमाणु हैं यदि वे लॉक या इंटरलॉक में हैं। * कथन। अकेले अस्थिरता आपके प्रश्न की शर्तों के तहत पर्याप्त नहीं है

5

मैं यहां बंदूक कूद रहा हूं लेकिन यह मुझे लगता है कि आप यहां दो मुद्दों को भ्रमित कर रहे हैं।

एक परमाणुता है, जो मेरे दिमाग में है कि एक ही ऑपरेशन (जिसे कई चरणों की आवश्यकता हो सकती है) किसी अन्य एकल ऑपरेशन के साथ संघर्ष में नहीं आना चाहिए।

दूसरा अस्थिरता है, यह मान कब बदलने की उम्मीद है, और क्यों।

पहले ले लो। यदि आपके दो-चरणीय ऑपरेशन के लिए आपको वर्तमान मान को पढ़ने, इसे संशोधित करने और इसे वापस लिखने की आवश्यकता होती है, तो आप निश्चित रूप से लॉक चाहते हैं, जब तक कि इस पूरे ऑपरेशन को एक ही CPU निर्देश में अनुवादित नहीं किया जा सकता है जो कि काम कर सकता है डेटा की एकल कैश लाइन।

हालांकि, दूसरा मुद्दा यह है कि, जब आप लॉकिंग चीज कर रहे हों, तो अन्य धागे क्या देखेंगे।

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

यह ज्ञान कंपाइलर को एक लूप या कोड के समान ब्लॉक से पहले एक बार रजिस्टर में मूल्य को उठाने की अनुमति देता है, और उस विशेष कोड के लिए फ़ील्ड से मूल्य को फिर से पढ़ नहीं सकता है।

बहु-थ्रेडिंग के साथ, इससे आपको कुछ समस्याएं मिल सकती हैं। ऑप्टिमाइज़ेशन के कारण एक थ्रेड ने मूल्य समायोजित किया हो सकता है, और दूसरा थ्रेड, कुछ समय के लिए इस मान को नहीं पढ़ेगा, क्योंकि जानता है कि यह नहीं बदला है।

तो जब आप volatile के रूप में फ़ील्ड को ध्वजांकित करते हैं तो आप मूल रूप से संकलक को बता रहे हैं कि यह किसी भी बिंदु पर इसका वर्तमान मूल्य नहीं है, हर बार इसे मूल्य की आवश्यकता होने पर स्नैपशॉट को पकड़ने के अलावा।

ताले कई-चरण संचालन को हल करते हैं, अस्थिरता संभालती है कि संकलक एक रजिस्टर में फ़ील्ड मान कैश करता है, और साथ में वे और अधिक समस्याएं हल करेंगे।

यह भी ध्यान रखें कि यदि किसी फ़ील्ड में कुछ ऐसा होता है जिसे एकल सीपीयू-निर्देश में पढ़ा नहीं जा सकता है, तो आप शायद इसे पढ़ने के लिए भी लॉक करना चाहते हैं।

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


संपादित: टिप्पणी का जवाब करने के लिए, कि volatile पढ़ें/लिखें आपरेशन के atomicity की गारंटी देता है, कि अच्छी तरह से, सच है, एक तरह से, क्योंकि volatile कीवर्ड फ़ील्ड से बड़े होते हैं के लिए लागू नहीं किया जा सकता 32-बिट, प्रभाव में क्षेत्र एकल-सीपीयू-निर्देश 32 और 64-बिट सीपीयू दोनों पर पढ़ने/लिखने योग्य बनाते हैं।और हां, यह मूल्य को जितना संभव हो सके रजिस्टर में रखने से रोक देगा।

तो टिप्पणी का हिस्सा गलत है, volatile 64-बिट मानों पर लागू नहीं किया जा सकता है।

ध्यान दें कि volatile में पढ़ने/लिखने के पुनर्मूल्यांकन के संबंध में कुछ अर्थशास्त्र हैं।

प्रासंगिक जानकारी के लिए, MSDN documentation या C# specification देखें, here, अनुभाग 10.5.3 मिला।

+0

बस स्पष्ट होने के लिए, अस्थिरता का आपका वर्णन सी/सी ++ में पाए गए जैसा लगता है। .NET में, अस्थिरता परमाणुता की गारंटी देता है और साथ ही इसे रजिस्टर के बजाए स्मृति में रखा जा सकता है। 64-बिट की तरह बड़े मूल्यों पर भी। – jalf

+0

@jalf: आप सी # में 64-बिट मानों पर अस्थिर कैसे निर्दिष्ट करते हैं ??? –

1

एक हार्डवेयर स्तर पर, एक से अधिक CPU ही परमाणु रैम स्थान पर simultanously कभी नहीं लिख सकते हैं: यह एक बहुत अच्छी पढ़ने है। एक परमाणु पढ़ने/लिखने का ऑपरेशन का आकार CPU आर्किटेक्चर पर निर्भर करता है, लेकिन आमतौर पर 32-बिट आर्किटेक्चर पर 1, 2 या 4 बाइट्स होता है। हालांकि, यदि आप परिणाम को वापस पढ़ने का प्रयास करते हैं तो हमेशा एक मौका होता है कि एक और सीपीयू ने उसी रैम स्थान पर लिखा है। निम्न स्तर पर, स्पिन-लॉक आमतौर पर साझा स्मृति तक पहुंच को सिंक्रनाइज़ करने के लिए उपयोग किए जाते हैं। एक उच्च स्तर की भाषा में, इस तरह के तंत्र कहा जा सकता है उदा। महत्वपूर्ण क्षेत्रों

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

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