"वाष्पशील" कीवर्ड किसके लिए उपयोग किया जाता है?


130

मैंने volatileकीवर्ड के बारे में कुछ लेख पढ़े लेकिन मैं इसका सही उपयोग नहीं कर पाया। क्या आप मुझे बता सकते हैं कि C # और Java में इसका क्या उपयोग होना चाहिए?


1
अस्थिरता के साथ समस्याओं में से एक यह है कि इसका मतलब एक से अधिक चीजें हैं। यह संकलक को फंकी ऑप्टिमाइज़ेशन नहीं करने के लिए जानकारी होना एक सी विरासत है। इसका अर्थ यह भी है कि एक्सेस में अवरोधों का उपयोग किया जाना चाहिए। लेकिन ज्यादातर मामलों में यह केवल प्रदर्शन की लागत और / या लोगों को भ्रमित करता है। : पी
AnorZaken

जवाबों:


93

C # और Java दोनों के लिए, "अस्थिर" कंपाइलर को बताता है कि एक वैरिएबल के मूल्य को कभी भी कैश नहीं करना चाहिए क्योंकि इसका मान प्रोग्राम के दायरे से बाहर बदल सकता है। कंपाइलर तब किसी भी ऑप्टिमाइजेशन से बच जाएगा, जिसके परिणामस्वरूप चर "इसके नियंत्रण के बाहर" परिवर्तित होने पर समस्या हो सकती है।


@ टॉम - विधिवत उल्लेख किया, सर - और संशोधित।
:

11
यह अभी भी है बहुत है कि तुलना में अधिक सूक्ष्म।
टॉम हॉल्टिन -

1
गलत। कैशिंग को नहीं रोकता है। मेरा जवाब देखिए।
dgg65536 2

168

इस उदाहरण पर विचार करें:

int i = 5;
System.out.println(i);

कंपाइलर इसे केवल 5 प्रिंट करने के लिए अनुकूलित कर सकता है, जैसे:

System.out.println(5);

हालांकि, अगर एक और धागा है जो बदल सकता है i, तो यह गलत व्यवहार है। यदि एक और धागा i6 हो जाता है, तो अनुकूलित संस्करण अभी भी 5 प्रिंट करेगा।

volatileकीवर्ड ऐसे अनुकूलन और कैशिंग से बचाता है, और इस तरह से उपयोगी है जब एक चर एक और धागा द्वारा बदला जा सकता।


3
मेरा मानना ​​है कि अनुकूलन अभी भी iचिह्नित के रूप में मान्य होगा volatile। जावा में यह सभी रिश्तों से पहले होता है
टॉम हॉल्टिन -

पोस्टिंग के लिए धन्यवाद, इसलिए किसी भी तरह अस्थिर में वैरिएबल लॉकिंग के साथ कनेक्शन हैं?
Mircea

@ मिरेका: यही मुझे बताया गया था कि कुछ को अस्थिर के रूप में चिह्नित करना सभी के बारे में था: किसी क्षेत्र को अस्थिर के रूप में चिह्नित करना थ्रेड को दिए गए चर के लिए एक सुसंगत मूल्य देखने के लिए अनुमति देने के लिए कुछ आंतरिक तंत्र का उपयोग करेगा, लेकिन ऊपर दिए गए उत्तर में इसका उल्लेख नहीं किया गया है ... शायद कोई इसकी पुष्टि कर सके या नहीं? धन्यवाद
npinti

5
@Sjoerd: मुझे यकीन नहीं है कि मैं इस उदाहरण को समझता हूं। यदि iएक स्थानीय चर है, तो कोई भी अन्य धागा इसे बदल नहीं सकता है। यदि यह एक फ़ील्ड है, तो कंपाइलर कॉल को ऑप्टिमाइज़ नहीं कर सकता है जब तक कि यह न हो final। मुझे नहीं लगता कि संकलक यह मानकर आधारित अनुकूलन कर सकता है कि कोई फ़ील्ड "दिखता है" finalजब इसे स्पष्ट रूप से घोषित नहीं किया जाता है।
पॉलीजेन लुब्रिकेंट 15

1
C # और जावा C ++ नहीं हैं। यह सही नहीं है। यह कैशिंग को नहीं रोकता है और यह अनुकूलन को नहीं रोकता है। यह रीड-अचीवमेंट और स्टोर-रिलीज़ सिमेंटिक्स के बारे में है, जो कि कमजोर ऑर्डर किए गए मेमोरी आर्किटेक्चर पर आवश्यक हैं। यह सट्टा निष्पादन के बारे में है।
doug65536

40

यह समझने के लिए कि एक चर में क्या अस्थिर होता है, यह समझना महत्वपूर्ण है कि क्या होता है जब चर अस्थिर नहीं होता है।

  • चर गैर-अस्थिर है

जब दो धागे A & B एक गैर-वाष्पशील चर तक पहुंच रहे हैं, तो प्रत्येक धागा स्थानीय कैश में चर की एक स्थानीय प्रतिलिपि बनाए रखेगा। थ्रेड ए द्वारा स्थानीय थ्रेड में किए गए कोई भी परिवर्तन थ्रेड बी को दिखाई नहीं देंगे।

  • चर अस्थिर है

जब चरों को अस्थिर घोषित किया जाता है, तो इसका अनिवार्य रूप से मतलब होता है कि थ्रेड्स को ऐसे वैरिएबल को कैश नहीं करना चाहिए या दूसरे शब्दों में, थ्रेड्स को इन चरों के मूल्यों पर भरोसा नहीं करना चाहिए जब तक कि वे मुख्य मेमोरी से सीधे नहीं पढ़े जाते हैं।

तो, परिवर्तनशील अस्थिर कब बनाया जाए?

जब आपके पास एक चर होता है जिसे कई थ्रेड्स द्वारा एक्सेस किया जा सकता है और आप चाहते हैं कि हर थ्रेड उस वैरिएबल के नवीनतम अपडेटेड वैल्यू को प्राप्त करे, भले ही वैल्यू किसी अन्य थ्रेड / प्रोसेस / प्रोग्राम के बाहर अपडेट हो।


2
गलत। इसका "कैशिंग रोकने" से कोई लेना-देना नहीं है। यह संकलक निष्पादन के माध्यम से कंपाइलर, या सीपीयू हार्डवेयर द्वारा पुन: व्यवस्थित करने के बारे में है।
doug65536 2

37

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

वाष्पशील क्षेत्रों के लेखन में विमोचन शब्द हैं । इसका मतलब यह है कि यह गारंटी दी जाती है कि किसी भी मेमोरी को वाष्पशील चर पर लिखने की गारंटी दी जाती है, जब तक कि पिछली सभी मेमोरी राइट्स अन्य प्रोसेसर के लिए दिखाई न दें।

निम्नलिखित उदाहरण पर विचार करें:

something.foo = new Thing();

यदि fooएक वर्ग में एक सदस्य चर है, और अन्य सीपीयू द्वारा संदर्भित ऑब्जेक्ट उदाहरण तक पहुंच है something, तो वे मूल्य fooपरिवर्तन को देख सकते हैं इससे पहले कि Thingनिर्माणकर्ता में लिखी गई मेमोरी विश्व स्तर पर दिखाई दे! यह वह है जो "कमजोर रूप से आदेशित स्मृति" का अर्थ है। यह तब भी हो सकता है जब कंपाइलर में स्टोर से पहले कंस्ट्रक्टर के सभी स्टोर हों foo। अगर fooहै volatileतो दुकान में fooरिलीज अर्थ विज्ञान होगा, और हार्डवेयर की गारंटी देता है लिखने से पहले राईट के सभी कि करने के लिए fooलिखने के लिए अनुमति देने से पहले अन्य प्रोसेसर के लिए दिखाई दे रहे हैं fooहोने के लिए।

यह कैसे संभव है कि fooलेखों को इतनी बुरी तरह से पुन: व्यवस्थित किया जा सके? यदि कैश लाइन होल्डिंग fooकैश में है, और कंस्ट्रक्टर में स्टोर कैश से चूक गए हैं, तो स्टोर के लिए यह संभव है कि कैश मिस को लिखने की तुलना में बहुत जल्द पूरा हो जाए।

इंटेल से (भयानक) इटेनियम वास्तुकला ने कमजोर रूप से स्मृति का आदेश दिया था। मूल XBox 360 में उपयोग किए गए प्रोसेसर ने कमजोर रूप से मेमोरी का आदेश दिया था। बहुत ही लोकप्रिय ARMv7-A सहित कई एआरएम प्रोसेसर ने कमजोर रूप से स्मृति का आदेश दिया है।

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

एक अधिक पूर्ण उदाहरण "डबल-चेकिंग लॉकिंग" पैटर्न है। इस पैटर्न का उद्देश्य किसी वस्तु को प्रारंभिक रूप से आलसी करने के लिए हमेशा लॉक का अधिग्रहण करने से बचना है।

स्नैग्ड

public class MySingleton {
    private static object myLock = new object();
    private static volatile MySingleton mySingleton = null;

    private MySingleton() {
    }

    public static MySingleton GetInstance() {
        if (mySingleton == null) { // 1st check
            lock (myLock) {
                if (mySingleton == null) { // 2nd (double) check
                    mySingleton = new MySingleton();
                    // Write-release semantics are implicitly handled by marking
                    // mySingleton with 'volatile', which inserts the necessary memory
                    // barriers between the constructor call and the write to mySingleton.
                    // The barriers created by the lock are not sufficient because
                    // the object is made visible before the lock is released.
                }
            }
        }
        // The barriers created by the lock are not sufficient because not all threads
        // will acquire the lock. A fence for read-acquire semantics is needed between
        // the test of mySingleton (above) and the use of its contents. This fence
        // is automatically inserted because mySingleton is marked as 'volatile'.
        return mySingleton;
    }
}

इस उदाहरण में, स्टोर में MySingletonस्टोर करने से पहले कंस्ट्रक्टर के स्टोर अन्य प्रोसेसर के लिए दृश्यमान नहीं हो सकते हैं mySingleton। यदि ऐसा होता है, तो अन्य धागे जो मायसिंगलटन पर नज़र रखते हैं, वे एक ताला का अधिग्रहण नहीं करेंगे और वे आवश्यक रूप से निर्माणकर्ता को राइट्स नहीं लेंगे।

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


अच्छे खर्च। इसके अलावा अच्छा डबल-चेक लॉकिंग उदाहरण। हालाँकि, मैं अभी भी अनिश्चित हूं कि कब उपयोग करना है क्योंकि मैं कैशिंग पहलुओं के बारे में चिंतित हूं। यदि मैं एक कतार कार्यान्वयन लिखता हूं जहां केवल 1 धागा लिख ​​रहा होगा और केवल 1 धागा पढ़ रहा होगा, तो क्या मैं बिना ताले के प्राप्त कर सकता हूं और केवल अपने सिर और पूंछ "संकेत" को अस्थिर के रूप में चिह्नित कर सकता हूं? मैं यह सुनिश्चित करना चाहता हूं कि पाठक और लेखक दोनों सबसे अधिक मूल्य देखें।
निकु

दोनों headऔर tailजरूरत संभालने से निर्माता को रोकने के लिए अस्थिर होने के लिए tailपरिवर्तन नहीं होगा, और यह मानते हुए से उपभोक्ता को रोकने के लिए headनहीं बदलेगा। इसके अलावा, headयह सुनिश्चित करने के लिए अस्थिर होना चाहिए कि कतार डेटा लिखता है जो विश्व स्तर पर स्टोर से पहले headदिखाई दे रहा है।
doug65536

+1, नवीनतम / "सबसे अपडेटेड" शब्दों की तरह दुर्भाग्य से विलक्षण सही मूल्य की अवधारणा है। वास्तविकता में दो प्रतियोगी एक ही समय में एक फिनिश लाइन को पार कर सकते हैं - एक सीपीयू पर दो कोर सटीक एक ही समय में लिखने का अनुरोध कर सकते हैं । सब के बाद, कोर काम नहीं कर रहे हैं - कि मल्टी कोर व्यर्थ कर देगा। अच्छी बहु-धागा सोच / डिज़ाइन को निम्न-स्तरीय "नवीनतमता" को लागू करने की कोशिश पर ध्यान केंद्रित नहीं करना चाहिए - स्वाभाविक रूप से नकली क्योंकि एक ताला बस एक कोर को मनमाने ढंग से w / o निष्पक्षता में एक स्पीकर का चयन करने के लिए मजबूर करता है - बल्कि इसे दूर डिजाइन करने का प्रयास करें ऐसी अप्राकृतिक अवधारणा की आवश्यकता है।
एंरजेन

34

अस्थिर कीवर्ड में दोनों जावा और सी # अलग अलग अर्थ है।

जावा

से जावा भाषा युक्ति :

एक क्षेत्र को अस्थिर घोषित किया जा सकता है, इस स्थिति में जावा मेमोरी मॉडल यह सुनिश्चित करता है कि सभी थ्रेड्स चर के लिए एक सुसंगत मूल्य देखें।

सी#

वाष्पशील कीवर्ड पर C # संदर्भ से :

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


पोस्ट करने के लिए बहुत-बहुत धन्यवाद, जैसा कि मैंने जावा में समझा है कि यह उस वैरिएबल को थ्रेड संदर्भ में लॉक करने जैसा काम करता है, और C # में यदि वेरिएबल के वैल्यू को न केवल प्रोग्राम से बदला जा सकता है, तो बाहरी कारक जैसे ओएस अपने वैल्यू को संशोधित कर सकता है ( नो लॉकिंग इम्प्लाइड) ... कृपया मुझे बताएं कि क्या मैंने उन अंतरों को सही समझा ...
Mircea

@ जावा में कोई लॉकिंग शामिल नहीं है, यह सिर्फ यह सुनिश्चित करता है कि वाष्पशील चर के अधिकतम मूल्य का उपयोग किया जाएगा।
krock

क्या जावा कुछ प्रकार के मेमोरी बैरियर का वादा करता है, या यह C ++ और C # की तरह है, जो केवल संदर्भ को ऑप्टिमाइज़ नहीं करने का वादा करता है?
स्टीवन सुदित

मेमोरी बैरियर एक कार्यान्वयन विवरण है। जावा वास्तव में क्या वादा करता है कि सभी पढ़े गए मूल्य को सबसे हाल के लेखन द्वारा लिखा जाएगा।
स्टीफन सी।

1
@StevenSudit हाँ, यदि हार्डवेयर के लिए एक अवरोध या लोड / अधिग्रहण या स्टोर / रिलीज़ की आवश्यकता है तो यह उन निर्देशों का उपयोग करेगा। मेरा जवाब देखिए।
doug65536 2

9

जावा में, "अस्थिर" का उपयोग जेवीएम को यह बताने के लिए किया जाता है कि चर का उपयोग एक ही समय में कई थ्रेड द्वारा किया जा सकता है, इसलिए कुछ सामान्य अनुकूलन लागू नहीं किए जा सकते हैं।

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


1

जब आप ऐसे डेटा को पढ़ रहे होते हैं जो गैर-वाष्पशील होते हैं, तो निष्पादित थ्रेड हमेशा अद्यतन मान प्राप्त कर सकता है या नहीं भी कर सकता है। लेकिन अगर वस्तु अस्थिर है, तो थ्रेड को हमेशा सबसे अधिक मूल्य मिलता है।


1
क्या आप अपने जवाब को फिर से लिख सकते हैं?
अनिरुद्ध गुप्ता

अस्थिर कीवर्ड आपको कैश्ड मान के बजाय सबसे अद्यतन मूल्य देगा।
सुभाष सैनी

0

अस्थिर समवर्ती समस्या को हल कर रहा है। उस मूल्य को सिंक में बनाने के लिए। यह कीवर्ड ज्यादातर थ्रेडिंग में उपयोग किया जाता है। जब एक ही चर को अद्यतन करने वाले कई थ्रेड।


1
मुझे नहीं लगता कि यह समस्या को हल करता है। यह एक उपकरण है जो कुछ परिस्थितियों में मदद करता है। उन स्थितियों के लिए अस्थिरता पर भरोसा न करें जहां एक दौड़ की स्थिति में, ताला की आवश्यकता होती है।
स्क्रेप्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.