इसके बारे में महत्वपूर्ण बिंदु volatile
:
- जावा में तुल्यकालन जावा कीवर्ड का उपयोग करके संभव है
synchronized
औरvolatile
और ताले।
- जावा में, हम
synchronized
परिवर्तनशील नहीं हो सकते । synchronized
एक चर के साथ कीवर्ड का उपयोग करना अवैध है और इसके परिणामस्वरूप संकलन त्रुटि होगी। synchronized
जावा में चर का उपयोग करने के बजाय , आप जावा volatile
चर का उपयोग कर सकते हैं , जो volatile
मुख्य स्मृति से चर के मूल्य को पढ़ने के लिए जेवीएम थ्रेड्स को निर्देश देगा और इसे स्थानीय रूप से कैश नहीं करेगा।
- यदि एक चर को कई थ्रेड्स के बीच साझा नहीं किया जाता है, तो
volatile
कीवर्ड का उपयोग करने की कोई आवश्यकता नहीं है ।
स्रोत
उदाहरण का उपयोग volatile
:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
पहला अनुरोध आने पर हम आलसी रूप से उदाहरण बना रहे हैं।
अगर हम _instance
वैरिएबल नहीं बनाते हैं volatile
तो थ्रेड जो बना रहा Singleton
है वह दूसरे थ्रेड से संवाद करने में सक्षम नहीं है। इसलिए यदि थ्रेड ए सिंगलटन उदाहरण का निर्माण कर रहा है और निर्माण के ठीक बाद, सीपीयू को नष्ट कर देता है आदि, अन्य सभी धागे मूल्य को देखने में सक्षम नहीं होंगे_instance
शून्य रूप में नहीं और उन्हें विश्वास होगा कि यह अभी भी अशक्त है।
ऐसा क्यों होता है? क्योंकि पाठक थ्रेड्स कोई लॉकिंग नहीं कर रहे हैं और जब तक कि लेखक थ्रेड एक सिंक्रनाइज़ किए गए ब्लॉक से बाहर नहीं निकलता है, तब तक मेमोरी को सिंक्रनाइज़ नहीं किया जाएगा और _instance
मुख्य मेमोरी में वैल्यू अपडेट नहीं की जाएगी। जावा में वोलेटाइल कीवर्ड के साथ, यह जावा द्वारा ही संभाला जाता है और इस तरह के अपडेट सभी रीडर थ्रेड्स द्वारा दिखाई देंगे।
निष्कर्ष : volatile
थ्रेड के बीच मेमोरी की सामग्री को संप्रेषित करने के लिए भी कीवर्ड का उपयोग किया जाता है।
बिना अस्थिर के उदाहरण का उपयोग:
public class Singleton{
private static Singleton _instance; //without volatile variable
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
ऊपर दिया गया कोड थ्रेड-सुरक्षित नहीं है। हालांकि यह एक बार फिर से सिंक्रनाइज़ किए गए ब्लॉक (प्रदर्शन कारणों के लिए) के भीतर उदाहरण के मूल्य की जांच करता है, जेआईटी कंपाइलर बायटेकोड को इस तरह से पुनर्व्यवस्थित कर सकता है कि निर्माण के पूरा होने से पहले इंस्टेंस का संदर्भ सेट हो जाता है। इसका मतलब यह है कि विधि getInstance () एक ऐसी वस्तु लौटाती है जो शायद पूरी तरह से शुरू नहीं की गई है। कोड थ्रेड को सुरक्षित बनाने के लिए, अस्थिर अस्थिर संस्करण के लिए जावा 5 के बाद से कीवर्ड वाष्पशील का उपयोग किया जा सकता है। वैरायटी के रूप में चिह्नित वेरिएबल्स केवल अन्य थ्रेड्स के लिए दिखाई देते हैं एक बार जब ऑब्जेक्ट का निर्माता पूरी तरह से अपने निष्पादन को समाप्त कर लेता है।
स्रोत
volatile
जावा में उपयोग :
असफल-तेज़ पुनरावृत्तियों को आमतौरvolatile
पर सूची ऑब्जेक्ट पर एक काउंटर का उपयोग करके लागू किया जाता है ।
- जब सूची को अद्यतन किया जाता है, तो काउंटर को बढ़ा दिया जाता है।
- जब एक
Iterator
बनाया जाता है, तो काउंटर का वर्तमान मूल्य अंदर एम्बेडेड होता हैIterator
ऑब्जेक्ट ।
- जब एक
Iterator
ऑपरेशन किया जाता है, तो विधि दो काउंटर मानों की तुलना करती है और ConcurrentModificationException
यदि वे अलग-अलग हैं तो फेंकता है ।
असफल-सुरक्षित पुनरावृत्तियों का कार्यान्वयन आमतौर पर हल्का होता है। वे आम तौर पर विशिष्ट सूची कार्यान्वयन के डेटा संरचनाओं के गुणों पर भरोसा करते हैं। कोई सामान्य पैटर्न नहीं है।
volatile
JSR 133 में परिभाषित नए जावा मेमोरी मॉडल के साथ आई थी: जब एक थ्रेड एकvolatile
वैरिएबल को पढ़ता है, तो यह न केवल अंतिम मूल्य को किसी अन्य थ्रेड द्वारा लिखे गए देखता है, बल्कि अन्य सभी वैरिएबल को भी लिखता है जोvolatile
लेखन के समय उस दूसरे सूत्र में दिखाई दे रहे थे । इस उत्तर और इस संदर्भ को देखें ।