मान लें कि हमारे पास बहुत ही सरल जावा क्लास MyClass
है।
सिंक्रनाइज़ किए गए ब्लॉक के माध्यम से जावा में थ्रेड-सुरक्षित कक्षा
यह सच अपरिवर्तनीय
public class MyClass { private final int number; public MyClass(int number) { this.number = number; } public int getNumber() { return number; } }
मेक क्षेत्र
number
volatile
करें:public class MyClass { private int number; public MyClass(int number) { this.number = number; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } }
तीन तरीके धागा सुरक्षित जावा वर्ग है जो किसी राज्य है निर्माण करने के लिए कर रहे हैं।
public class MyClass { private volatile int number; public MyClass(int number) { this.number = number; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } }
एक
synchronized
ब्लॉक का उपयोग करें। अभ्यास में जावा कंसुरेंसी के अध्याय 4.3.5 में वर्णित इस दृष्टिकोण का क्लासिक संस्करण। और इस बारे में मजाकिया बात यह है कि इस पुस्तक के लिए इरेटा में उल्लिखित उदाहरण में एक त्रुटि है।public class MyClass { private int number; public MyClass(int number) { setNumber(number); } public synchronized int getNumber() { return number; } public synchronized void setNumber(int number) { this.number = number; } }
एक और तथ्य यह है कि चर्चा के संदर्भ में जोड़ा जाना चाहिए नहीं है। एक multhithreaded वातावरण में JVM synchronized
ब्लॉक के बाहर निर्देशों को पुन: व्यवस्थित करने के लिए स्वतंत्र है जो तार्किक अनुक्रम को संरक्षित करता है और होता है- जेवीएम द्वारा निर्दिष्ट संबंधों से पहले होता है। यह प्रकाशन ऑब्जेक्ट का कारण बन सकता है जो अभी तक किसी अन्य थ्रेड के लिए ठीक से नहीं बनाया गया है।
मुझे तीसरे मामले के बारे में कुछ प्रश्न हैं। JVM intstructions को पुन: व्यवस्थित करने के लिए है और इसलिए डिफ़ॉल्ट मान के साथ वस्तु को प्रकाशित करने के लिए
public class MyClass {
private int number;
public MyClass(int number) {
synchronized (this){
this.number = number;
}
}
public synchronized int getNumber() {
return number;
}
public synchronized void setNumber(int number) {
this.number = number;
}
}
एक पुनर्व्यवस्था तीसरे मामले में रोका जाएगा या यह संभव:
यह कोड का एक टुकड़ा निम्नलिखित के बराबर होगी क्षेत्र में
number
?यदि दूसरे प्रश्न का उत्तर हाँ है तो मेरे पास एक और सवाल है।
public class MyClass { private int number; public MyClass(int number) { synchronized (new Object()){ this.number = number; } } public synchronized int getNumber() { return number; } public synchronized void setNumber(int number) { this.number = number; } }
इस अजीब दिखने synchronized (new Object())
पुन: क्रम प्रभाव को रोकने के लिए माना जाता है। क्या ये काम करेगा?
बस स्पष्ट होने के लिए, इन सभी उदाहरणों में कोई व्यावहारिक अनुप्रयोग नहीं है। मैं multithreading की बारीकियों के बारे में सिर्फ उत्सुक हूँ।
यह कुछ करता है (निर्माण थ्रेड में उसके बाद होने वाली किसी भी चीज़ से पहले पूरा करने के लिए ब्लॉक में सबकुछ मजबूर करता है, इसलिए अगर निर्माण धागा तो कन्स्ट्रक्टर रिटर्न के बाद तुरंत किसी अन्य थ्रेड के संदर्भ को पास कर देता है, तो आपको इसकी आवश्यकता नहीं है गैर-अंतिम क्षेत्रों के बारे में चिंता करें।) यह * सभी * समवर्ती खतरों को कवर करने के लिए * पर्याप्त * नहीं करता है। – Affe
@Affe एक थ्रेड के भीतर आप कोड को उन क्रम में देखने के लिए पहले से ही गारंटी दे रहे हैं - कोड सिंक्रनाइज़ेशन की आवश्यकता नहीं है। लेकिन डेटा रेस के कारण, एक ही थ्रेड को उसी क्रम में उन प्रभावों को देखने की आवश्यकता नहीं है। दूसरे शब्दों में, यदि थ्रेड ए 'ए, बी, सी' करता है (उदाहरण के लिए, 'ए' सिंक है,' बी' फ़ील्ड असाइनमेंट है, 'सी'' नया' के बाद संदर्भ सेट कर रहा है), थ्रेड बी अगर सीएबी' देखने की अनुमति है तो किनारे से पहले नहीं होता है - जो 'सिंक्रनाइज़ (नया ऑब्जेक्ट()) कभी प्रदान नहीं किया जाएगा। उदाहरण के लिए, यदि थ्रेड बी एक अलग कोर पर है, तो 'सी' 'ए' से पहले फ़्लश हो सकता है। – yshavit
असाइनमेंट बी के आस-पास के पहले धागे के भीतर सिंक्रनाइज़ करना बी को संदर्भ सी सेट करने से पहले दृश्यमान होने के लिए मजबूर करता है। सिंक्रनाइज़ किए गए ब्लॉक की स्मृति स्थिरता दुष्प्रभावों को साइड इफेक्ट्स को बहिष्कृत करने के लिए जोड़ा नहीं जाता है। वे अभी भी पहले धागे में किए गए संचालन के लिए आवेदन करते हैं चाहे अन्य थ्रेड ऑब्जेक्ट मॉनीटर के लिए होता है या नहीं। – Affe