यदि एक सिंक्रनाइज़ विधि एक और सिंक्रनाइज़ विधि को कॉल करती है, तो क्या यह थ्रेड सुरक्षित है?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
यदि एक सिंक्रनाइज़ विधि एक और सिंक्रनाइज़ विधि को कॉल करती है, तो क्या यह थ्रेड सुरक्षित है?
void synchronized method1() {
method2()
}
void synchronized method2() {
}
जवाबों:
हां, जब आप तरीकों को चिह्नित करते हैं synchronized
, तो आप वास्तव में ऐसा कर रहे हैं:
void method1() {
synchronized (this) {
method2()
}
}
void method2() {
synchronized (this) {
}
}
जब मेथड 1 से मेथड कॉल थ्रेड 2 में हो जाता है, तो यह सुनिश्चित करेगा कि यह लॉक को पकड़ता है this
, जिसे यह पहले से ही है, और फिर यह गुजर सकता है।
जब थ्रेड सीधे मेथ 1 या मेथड 2 में जाता है, तो यह तब तक ब्लॉक रहेगा जब तक यह लॉक ( this
) प्राप्त नहीं कर सकता है , और फिर यह प्रवेश करेगा।
जैसा कि जेम्स ब्लैक ने टिप्पणियों में कहा है, आपको विधि बॉडी के अंदर क्या करना है, इसके बारे में जागरूक होना चाहिए।
private final List<T> data = new ArrayList<T>();
public synchronized void method1() {
for (T item : data) {
// ..
}
}
public void method3() {
data.clear();
}
अचानक यह थ्रेड सुरक्षित नहीं है क्योंकि आप ConcurrentModificationException
अपने भविष्य को देख रहे हैं क्योंकि method3
यह अनसिंक्रनाइज़ है, और इस तरह थ्रेड ए द्वारा कॉल किया जा सकता है जबकि थ्रेड बी में काम कर रहा है method1
।
method3
असुरक्षित थ्रेडिंग ऑपरेशन दिखाता है, लेकिन आप रीक्रेंट सिंक्रोनाइज़ेशन के बारे में हाजिर हैं।
एक विधि है जिसे सिंक्रोनाइज़्ड कॉल के साथ चिह्नित किया जाता है जो एक अन्य सिंक्रनाइज़ विधि थ्रेड सुरक्षित है।
सामान्य तौर पर, यह कहना संभव नहीं है। यह इस बात पर निर्भर करता है कि विधियां क्या करती हैं, और उसी और अन्य वर्गों पर अन्य विधियां क्या करती हैं।
हालांकि, हम यह सुनिश्चित कर सकते हैं कि विभिन्न थ्रेड द्वारा बनाई गई एक ही ऑब्जेक्ट पर method1 और method2 पर कॉल एक साथ निष्पादित नहीं होंगे। इस तरीके के आधार पर, यह कहने के लिए पर्याप्त हो सकता है कि इन विधियों के संबंध में वर्ग थ्रेड-सुरक्षित है।
जावा ट्यूटोरियल साइट से http://download.oracle.com/javase/tutorial/essential/concurrency/syncmn.html
इंटरलेव के लिए एक ही वस्तु पर सिंक्रनाइज़ किए गए तरीकों के दो आह्वान संभव नहीं है। जब कोई थ्रेड किसी ऑब्जेक्ट के लिए एक सिंक्रोनाइज़ की गई विधि को निष्पादित कर रहा होता है, तो अन्य सभी थ्रेड्स जो ऑब्जेक्ट के साथ पहले थ्रेड को निष्पादित करने तक एक ही ऑब्जेक्ट ब्लॉक (सस्पेंड निष्पादन) के लिए सिंक्रनाइज़ किए गए तरीकों को लागू करते हैं।
जब कोई सिंक्रनाइज़ किए गए तरीके से बाहर निकलता है, तो यह स्वचालित रूप से एक ही ऑब्जेक्ट के लिए सिंक्रनाइज़ विधि के किसी भी बाद के आह्वान के साथ होता है-पहले संबंध स्थापित करता है। यह गारंटी देता है कि ऑब्जेक्ट की स्थिति में परिवर्तन सभी थ्रेड्स को दिखाई देते हैं
इसलिए जावा यह सुनिश्चित करेगा कि यदि 2 थ्रेड्स एक ही विधि को निष्पादित कर रहे हैं, तो विधियाँ समान रूप से निष्पादित नहीं होंगी, लेकिन एक के बाद एक।
लेकिन आपको Lience की समस्या के बारे में पता होना चाहिए, http://download.oracle.com/javase/tutorial/essential/concurrency/starvelive.html
और यह भी कि क्या आप uncessarily ताला लगा रहे हैं, कोड में कारण आप का इस्तेमाल किया यह जो पूरी वस्तु ताले, यदि आपका वस्तु केवल एक चर करने के लिए सिंक उपयोग की जरूरत है आप सिर्फ इतना है कि चर ताला चाहिए।
synchronized (this.someVar)
आप उस वस्तु को देख रहे हैं जिसका संदर्भ इसमें रखा गया है someVar
। भेद बहुत महत्वपूर्ण है।