"हाय, अमीगो!"

"हाय, ऐली!"

"मैं आपको अस्थिर संशोधक के बारे में बताना चाहता हूं। क्या आप जानते हैं कि वह क्या है?"

"धागों के साथ कुछ करना है। मुझे ठीक से याद नहीं है।"

"फिर सुनें। यहां आपके लिए कुछ तकनीकी विवरण दिए गए हैं:"

"एक कंप्यूटर में दो प्रकार की मेमोरी होती है: वैश्विक (साधारण) मेमोरी और प्रोसेसर में निर्मित मेमोरी। अंतर्निहित प्रोसेसर मेमोरी को रजिस्टरों में विभाजित किया जाता है, एक प्रथम-स्तरीय कैश (L1), द्वितीय-स्तरीय कैश (L2), और तृतीय-स्तर (L3)।"

"इस प्रकार की मेमोरी की अलग-अलग गति होती है। सबसे तेज़ और सबसे छोटी मेमोरी रजिस्टर होती है, फिर प्रोसेसर कैश (L1, L2, L3), और अंत में ग्लोबल मेमोरी (सबसे धीमी)।"

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

"क्या इस प्रक्रिया को किसी तरह नियंत्रित किया जा सकता है?"

"वास्तव में नहीं। सारा काम जावा मशीन द्वारा किया जाता है। जब प्रदर्शन को अनुकूलित करने की बात आती है तो यह बहुत बुद्धिमान होता है।"

"लेकिन यहाँ मैं आपको यह क्यों बता रहा हूँ। एक छोटी सी समस्या है। जब दो धागे एक ही चर के साथ काम कर रहे हों, तो प्रत्येक एक कॉपी को अपने स्थानीय कैश में संग्रहीत कर सकता है। और फिर एक धागा चर को बदल सकता है, लेकिन दूसरा हो सकता है कि परिवर्तन दिखाई न दे, क्योंकि यह अभी भी चर की अपनी प्रति के साथ काम कर रहा है।"

"अच्छा, फिर क्या किया जा सकता है?"

"जावा के रचनाकारों ने इस स्थिति के लिए एक विशेष कीवर्ड प्रदान किया: वाष्पशील। यदि एक चर को विभिन्न थ्रेड्स से एक्सेस किया जाता है, तो आपको इसे अस्थिर संशोधक के साथ चिह्नित करने की आवश्यकता होती है, इसलिए जावा मशीन इसे कैश में नहीं डालती है। यह आमतौर पर ऐसा होता है दिखता है:"

public volatile int count = 0;

"ओह, मुझे याद है। आप पहले ही इसका उल्लेख कर चुके हैं। मुझे यह पहले से ही पता है।"

"बेशक तुम करते हो। लेकिन तुम्हें यह तभी याद आया जब मैंने तुमसे कहा था।"

"एर, ठीक है, मैं थोड़ा भूल गया हूँ।"

"दोहराव सीखने की जननी है!"

"यहां अस्थिर संशोधक के बारे में कुछ नए तथ्य हैं। वाष्पशील संशोधक केवल गारंटी देता है कि चर को सुरक्षित रूप से पढ़ा और लिखा जाएगा। यह गारंटी नहीं देता है कि इसे सुरक्षित रूप से बदला जाएगा।"

"क्या फर्क पड़ता है?"

"देखो कि एक चर कैसे बदला जाता है:"

कोड वास्तव में क्या होता है: विवरण
count++
register = count;

register = register+1;

count = register;
चरण 1।
चर गणना का मान वैश्विक मेमोरी से प्रोसेसर रजिस्टर में कॉपी किया जाता है।

चरण 2.
प्रोसेसर के अंदर, रजिस्टर वेरिएबल को 1 से बढ़ाया जाता है।

चरण 3.
वेरिएबल का मान प्रोसेसर से ग्लोबल मेमोरी में कॉपी किया जाता है।

"वाह! तो, सभी चर केवल प्रोसेसर में ही बदले जाते हैं?"

"हां।"

"और मूल्यों को आगे और पीछे कॉपी किया जाता है: स्मृति से प्रोसेसर और पीछे?"

"हां।"

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

"लेकिन जावा मशीन इस बात की गारंटी नहीं देती है कि चरण 1 और 3 के बीच कोई थ्रेड स्विचिंग नहीं होगी।"

"तो, चर को 1 से बढ़ाना वास्तव में तीन ऑपरेशन हैं?"

"हाँ।"

"और यदि दो धागे एक साथ गिनती ++ निष्पादित करना चाहते हैं, तो वे एक दूसरे के साथ हस्तक्षेप कर सकते हैं?"

"हाँ, इसे देखें:"

थ्रेड 1 धागा 2 परिणाम
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"तो, आप चर का उपयोग कर सकते हैं, लेकिन इसे बदलना अभी भी जोखिम भरा है?"

"ठीक है, आप इसे बदल सकते हैं, बस सावधान रहें ☺"

"कैसे?"

" सिंक्रनाइज़  हमारा सबसे अच्छा दोस्त है।"

"अच्छा ऐसा है।"