मैं यहां बंदूक कूद रहा हूं लेकिन यह मुझे लगता है कि आप यहां दो मुद्दों को भ्रमित कर रहे हैं।
एक परमाणुता है, जो मेरे दिमाग में है कि एक ही ऑपरेशन (जिसे कई चरणों की आवश्यकता हो सकती है) किसी अन्य एकल ऑपरेशन के साथ संघर्ष में नहीं आना चाहिए।
दूसरा अस्थिरता है, यह मान कब बदलने की उम्मीद है, और क्यों।
पहले ले लो। यदि आपके दो-चरणीय ऑपरेशन के लिए आपको वर्तमान मान को पढ़ने, इसे संशोधित करने और इसे वापस लिखने की आवश्यकता होती है, तो आप निश्चित रूप से लॉक चाहते हैं, जब तक कि इस पूरे ऑपरेशन को एक ही CPU निर्देश में अनुवादित नहीं किया जा सकता है जो कि काम कर सकता है डेटा की एकल कैश लाइन।
हालांकि, दूसरा मुद्दा यह है कि, जब आप लॉकिंग चीज कर रहे हों, तो अन्य धागे क्या देखेंगे।
एनईटी में volatile
फ़ील्ड एक ऐसा क्षेत्र है जहां संकलक मनमाने ढंग से समय पर बदल सकता है। एक थ्रेडेड दुनिया में, एक चर का परिवर्तन कुछ ऐसा होता है जो निर्देशों की अनुक्रमिक धारा में किसी बिंदु पर होता है ताकि संकलक जानता हो कि जब उसने कोड जोड़ा है जो इसे बदलता है, या कम से कम जब उसने बाहरी दुनिया को बुलाया है हो सकता है कि आपने इसे बदल दिया हो या नहीं, ताकि कोड लौटने के बाद, यह वही मूल्य न हो जो कॉल से पहले था।
यह ज्ञान कंपाइलर को एक लूप या कोड के समान ब्लॉक से पहले एक बार रजिस्टर में मूल्य को उठाने की अनुमति देता है, और उस विशेष कोड के लिए फ़ील्ड से मूल्य को फिर से पढ़ नहीं सकता है।
बहु-थ्रेडिंग के साथ, इससे आपको कुछ समस्याएं मिल सकती हैं। ऑप्टिमाइज़ेशन के कारण एक थ्रेड ने मूल्य समायोजित किया हो सकता है, और दूसरा थ्रेड, कुछ समय के लिए इस मान को नहीं पढ़ेगा, क्योंकि जानता है कि यह नहीं बदला है।
तो जब आप volatile
के रूप में फ़ील्ड को ध्वजांकित करते हैं तो आप मूल रूप से संकलक को बता रहे हैं कि यह किसी भी बिंदु पर इसका वर्तमान मूल्य नहीं है, हर बार इसे मूल्य की आवश्यकता होने पर स्नैपशॉट को पकड़ने के अलावा।
ताले कई-चरण संचालन को हल करते हैं, अस्थिरता संभालती है कि संकलक एक रजिस्टर में फ़ील्ड मान कैश करता है, और साथ में वे और अधिक समस्याएं हल करेंगे।
यह भी ध्यान रखें कि यदि किसी फ़ील्ड में कुछ ऐसा होता है जिसे एकल सीपीयू-निर्देश में पढ़ा नहीं जा सकता है, तो आप शायद इसे पढ़ने के लिए भी लॉक करना चाहते हैं।
उदाहरण के लिए, यदि आप 32-बिट सीपीयू पर हैं और 64-बिट मान लिख रहे हैं, तो लिखने के लिए ऑपरेशन को पूरा करने के लिए दो चरणों की आवश्यकता होगी, और यदि कोई अन्य सीपीयू 64-बिट पढ़ने के लिए प्रबंधन करता है चरण 2 से पहले मूल्य पूरा हो गया है, इसे पिछले मूल्य का आधा और नया आधा मिल जाएगा, अच्छी तरह से मिश्रित, जो पुराना हो जाने से भी बदतर हो सकता है।
संपादित: टिप्पणी का जवाब करने के लिए, कि volatile
पढ़ें/लिखें आपरेशन के atomicity की गारंटी देता है, कि अच्छी तरह से, सच है, एक तरह से, क्योंकि volatile
कीवर्ड फ़ील्ड से बड़े होते हैं के लिए लागू नहीं किया जा सकता 32-बिट, प्रभाव में क्षेत्र एकल-सीपीयू-निर्देश 32 और 64-बिट सीपीयू दोनों पर पढ़ने/लिखने योग्य बनाते हैं।और हां, यह मूल्य को जितना संभव हो सके रजिस्टर में रखने से रोक देगा।
तो टिप्पणी का हिस्सा गलत है, volatile
64-बिट मानों पर लागू नहीं किया जा सकता है।
ध्यान दें कि volatile
में पढ़ने/लिखने के पुनर्मूल्यांकन के संबंध में कुछ अर्थशास्त्र हैं।
प्रासंगिक जानकारी के लिए, MSDN documentation या C# specification देखें, here, अनुभाग 10.5.3 मिला।
यह * एक बहुत अच्छा पढ़ा गया है (और निश्चित रूप से एक +1 का हकदार है), लेकिन इसे सामान्य रूप से एसओ उत्तरों के लिए कुछ हद तक स्वयं निहित होने के लिए प्राथमिकता दी जाती है। यह अच्छा होगा अगर आपके उत्तर में उस आलेख के महत्वपूर्ण हिस्सों का सारांश शामिल है, तो बस (1) पृष्ठ को स्किम करने वाले लोग इसे देखेंगे, और (2) इसलिए लेख को स्थानांतरित या हटाए जाने पर उत्तर प्रासंगिक रहता है। – jalf