2011-07-24 21 views
8

किसी वस्तु लॉकिंग के संदर्भ में इन दो उदाहरणों के बीच अंतर के बारे में समझाएं सकता है:सिंक्रनाइज़ धागे और लॉकिंग

public void method1(){ 
    synchronized(this){ 
     .... 
    } 
} 

और

StringBuffer aStringBufferObject = new StringBuffer("A"); 

public void method2(){ 
    synchronized(aStringBufferObject){ 
     .... 
    } 
} 

मैं पहला उदाहरण पता पर एक ताला प्राप्त करेंगे this उदाहरण और दूसरा AStringBufferObject उदाहरण का लॉक प्राप्त करेगा। लेकिन मैं वास्तव में समझ नहीं पा रहा हूं कि दोनों का प्रभाव या अंतर क्या है।

उदाहरण के लिए, दूसरे उदाहरण में, क्या थ्रेड अभी भी सिंक्रनाइज़ किए गए ब्लॉक के अंदर कोड निष्पादित करने में सक्षम होंगे क्योंकि लॉक 'इस' उदाहरण से संबंधित नहीं है?

मुझे पता है कि एक विधि या कोड के ब्लॉक को सिंक्रनाइज़ करना एक ही समय में उस ब्लॉक/विधि तक पहुंचने के लिए कई धागे को रोकता है लेकिन वस्तु को लॉक करने के लिए निर्दिष्ट करने का उद्देश्य क्या है और वस्तु के तरीके में क्या अंतर है उपरोक्त उदाहरणों में निर्दिष्ट है?

+1

यह भी देखें [सिंक्रनाइज़ किए गए तरीके और थ्रेड लॉकिंग] (http://forums.oracle.com/forums/thread.jspa?threadID=2257647)। –

+0

यहां एक नज़र डालें: [जावा कंसुरेंसी/मल्टीथ्रेडिंग - ट्यूटोरियल] (http://www.vogella.de/articles/JavaConcurrency/article.html) –

+0

@ एंड्रयू: आह, हालांकि आप एक लेख का जिक्र कर रहे थे, लेकिन अब देखें कि यह एक बहु-पोस्ट है। –

उत्तर

8

ऑब्जेक्ट को लॉक करने के लिए निर्दिष्ट करने का उद्देश्य क्या है?

अक्सर, यह this पर या Class उदाहरण (स्थिर तरीकों के लिए) पर सिंक्रनाइज़ करने के लिए आसान है। लेकिन, ऐसे मामले हैं जहां आपको निहित लॉक (this) के बजाय किसी विशिष्ट ऑब्जेक्ट पर सिंक्रनाइज़ करने की आवश्यकता होगी। इस तरह के मामलों में शामिल हैं:

  • आप this का उपयोग किये बिना प्राइमेटिव तक पहुंच सिंक्रनाइज़ करना चाहते हैं। आप केवल Object एस पर सिंक्रनाइज़ कर सकते हैं क्योंकि प्रत्येक Object जावा में एक अंतर्निहित मॉनीटर से जुड़ा हुआ है। Primitives में ऐसे निहित मॉनीटर नहीं हैं, और इसलिए आपको लॉक ऑब्जेक्ट का उपयोग करने की आवश्यकता है। रैपर वर्गों का उपयोग करना एक खराब और गलत विकल्प है, खासकर यदि आप modifying the lock object in the guarded block समाप्त करते हैं।
  • आप किसी ऑब्जेक्ट पर सिंक्रनाइज़ करना चाहते हैं जो वास्तव में महत्वपूर्ण अनुभाग की सुरक्षा करता है, जब this पर सिंक्रनाइज़ करते समय थ्रेड सुरक्षा की गारंटी नहीं दी जाएगी। उदाहरण के लिए, यदि आप उदाहरण के लिए A के उदाहरणों में साझा किए गए उदाहरण को सिंक्रनाइज़ कर रहे हैं, तो A के उदाहरण पर सिंक्रनाइज़ करना बेकार है। एक धागा A का एक नया उदाहरण बना सकता है और सूची तक पहुंच प्राप्त कर सकता है, जबकि दूसरा धागा इसे संशोधित कर रहा है। यदि आप एक अलग लॉक का उपयोग करते हैं जो सभी धागे के लिए संघर्ष करना चाहिए तो आप सूची की रक्षा कर सकते हैं; यह लॉक A.class से जुड़ा हुआ हो सकता है, लेकिन यह कोई ऑब्जेक्ट हो सकता है जो समान गारंटी प्रदान करेगा।
  • आप यह सुनिश्चित करने के लिए लॉक स्प्लिटिंग करना चाहते हैं कि अलग-अलग संरक्षित ब्लॉक एक ही लॉक के बजाय विभिन्न ताले से सुरक्षित हैं। दूसरे शब्दों में, यदि यह विभिन्न धागे को विभिन्न महत्वपूर्ण खंडों तक पहुंचने के लिए अलग-अलग ताले हासिल करने की अनुमति देने के लिए थ्रेड-सुरक्षित है, तो आप प्रत्येक महत्वपूर्ण अनुभाग के लिए एक अलग लॉक रख सकते हैं।

    private Object method1Lock = new Object(); 
    private Object method2Lock = new Object(); 
    
    public void method1(){ 
        synchronized(method1Lock){ 
         .... 
        } 
    } 
    
    public void method2(){ 
        synchronized(method2Lock){ 
         .... 
        } 
    } 
    

    आप विभाजन ताले का उपयोग करते हैं तो आप यह सुनिश्चित कर सकते हैं कि method1 और method2 के समवर्ती निष्पादन वर्ग अपरिवर्तनशीलताओं का उल्लंघन नहीं करते हैं:

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


अपने अन्य सवाल पर,

उदाहरण के लिए, दूसरे उदाहरण में, सूत्र अभी भी सिंक्रनाइज़ ब्लॉक के अंदर कोड को निष्पादित करने में सक्षम हो जाएगा 'इस' उदाहरण?

दूसरे उदाहरण में, संरक्षित क्षेत्र में प्रवेश करने वाले किसी भी थ्रेड को aStringBufferObject से जुड़े लॉक को प्राप्त करना होगा। यदि एक अलग धागा उस ताला को पकड़ रहा है, तो वर्तमान धागा आगे नहीं बढ़ेगा। जब आप this निर्दिष्ट करते हैं, तो थ्रेड को वर्तमान ऑब्जेक्ट से जुड़े लॉक को प्राप्त करना होगा। दोनों मामलों में, थ्रेड को लॉक प्राप्त करना होगा; उदाहरण केवल उस ऑब्जेक्ट में अलग हैं जो लॉक के रूप में उपयोग किया जा रहा है।

2

किसी ऑब्जेक्ट पर सिंक्रनाइज़ करने का अर्थ है कि अन्य ऑब्जेक्ट्स जो एक ही ऑब्जेक्ट पर सिंक्रनाइज़ करते हैं, उन्हें प्रतीक्षा करनी होगी। उदाहरण के लिए:

public void methodA() { 
    synchronized(obj) { 
     //Do one job 
    } 
} 

public void methodB() { 
    synchronized(obj) { 
     //Do another job 
    } 
} 

आप एक सूत्र में methodA() फोन और फिर एक और धागा में methodB() कॉल करते हैं, methodB()methodA() खत्म होने से पहले पूरी नहीं होगी।

2

synchronized ब्लॉक एक मॉनिटर है, जो एक म्यूटेक्स को लॉक और अनलॉक करने के लिए विवरण से बाहर निकलता है। चूंकि जावा में प्रत्येक ऑब्जेक्ट में आंतरिक लॉक होता है (Object वर्ग का स्रोत कोड देखें), synchronized कथन का उपयोग करते समय, JVM आपको महत्वपूर्ण अनुभाग को सिंक्रनाइज़ करने में मदद करेगा। आप संकुल java.util.concurrent.locks पैकेज में ReentrantLock का उपयोग स्वयं ब्लॉक को सिंक्रनाइज़ भी कर सकते हैं।

संबंधित मुद्दे