2012-01-29 17 views
12

मैंने कहीं पढ़ा है कि synchronized(this)various reasons के लिए बचा जाना चाहिए। फिर भी कुछ सम्मानजनक कोड है कि मैं का सामना करना पड़ा का उपयोग करता है निर्माता में निम्नलिखित:सिंक्रनाइज़ (यह) और सिंक्रनाइज़ (ClassName.class) के बीच क्या अंतर है?

public SomeClass(Context context) { 
    if (double_checked_lock == null) { 
    synchronized (SomeClass.class) { 
     if (double_checked_lock == null) { 
     // some code here 
     } 
    } 
    } 
} 

वहाँ वास्तव में synchronized(this) और synchronized(SomeClass.class) के बीच एक अंतर है?

उत्तर

23

synchronized(this) वर्तमान वस्तु पर सिंक्रनाइज़ है, तो केवल एक ही धागे प्रत्येक उदाहरण उपयोग कर सकते हैं, लेकिन अलग धागे अलग-अलग विविधताएं पहुँच सकते हैं। जैसे आप प्रति थ्रेड एक उदाहरण हो सकता है।

यह आमतौर पर एक ही समय है, जो असंगत स्थिति बना सकते हैं पर एक वस्तु को अद्यतन करने से अधिक थ्रेड को रोकने के लिए उपयोगी है।

synchronized(SomeClass.class) वर्तमान वस्तु (या किसी अन्य वर्ग अगर एक कामना) की वर्ग पर सिंक्रनाइज़ है तो केवल एक समय में एक धागा उस वर्ग के किसी भी उदाहरणों पहुँच सकते हैं।

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

+1

+1। यह वर्ग और ऑब्जेक्ट लॉक के बीच अधिक स्पष्टता देता है। मुझे इससे बेहतर कुछ नहीं मिला। * समझने के लिए छोटा और सरल * – Ravi

5

this प्रत्येक उदाहरण के लिए अलग है।
ClassName.class नहीं है।

इसलिए, synchronized(this) कई उदाहरण एक साथ चलाने के लिए अनुमति देगा।

3

synchronized कीवर्ड, जब कक्षा पर class ताले पर लागू होता है, और जब यह वर्तमान ऑब्जेक्ट उदाहरण पर this ताले पर लागू होता है। जावा भाषा विशिष्टता से, खंड 8.4.3.6, 'synchronized Methods':

एक सिंक्रनाइज़ विधि एक मॉनिटर (§17.1) से पहले ही कार्यान्वित प्राप्त कर लेता है। कक्षा (स्थैतिक) विधि के लिए, विधि वर्ग के लिए क्लास ऑब्जेक्ट से जुड़े मॉनीटर का उपयोग किया जाता है। एक उदाहरण विधि के लिए, इस से जुड़े मॉनीटर (जिस ऑब्जेक्ट के लिए विधि लागू की गई थी) का उपयोग किया जाता है। 'इस' वर्तमान उदाहरण संदर्भ का उल्लेख है, तो बनाने कई उदाहरण हैं, उदाहरण के लिए, एक अलग उदाहरण का उपयोग करते हुए प्रत्येक थ्रेड कोई प्रभाव नहीं है और उस पर लॉक हो जाएगा:

1

इन पर लॉक करने के लिए 2 अलग वस्तु है। 'यह' केवल गैर स्थैतिक संदर्भ पर संदर्भित किया जा सकता है।
'क्लास' जावा क्लास की एक स्थिर सदस्य है और इसका ठीक एक उदाहरण है। आप इसे स्थैतिक और गैर स्थैतिक संदर्भ दोनों में लॉक कर सकते हैं।

1

synchronized(this) ऑब्जेक्ट के उदाहरण पर सिंक्रनाइज़ करता है।

synchronized(SomeClass.class) क्लास ऑब्जेक्ट का उदाहरण उपयोग करता है जो कुछ क्लास का प्रतिनिधित्व करता है, जो एक ही क्लासलोडर में सभी उदाहरणों के लिए वैश्विक है।

इस प्रकार, ये अलग-अलग अर्थशास्त्र के साथ अलग-अलग संरचनाएं हैं।

अकेले synchronized का उपयोग करके, या एक विधि संशोधक के रूप में, उदाहरण के सेमफोर पर भी सिंक्रनाइज़ करता है, जिसे आम तौर पर साझा संसाधन (यानी एक सूची) के रूप में उस उदाहरण तक पहुंचने वाले एकाधिक धागे के बीच विवाद को रोकने के लिए उपयोग किया जाता है।

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

class MySharedResourceClass { 

    private SomeClass lock = new SomeClass(); 

    public doSomething() { 
     synchronized (lock) { 
      // Do something here 
     } 
    } 
} 
2

प्रत्येक जावा ऑब्जेक्ट में लॉक हो सकता है। इस लॉक को एक समय में अधिकतम एक थ्रेड पर रखा जा सकता है, किसी अन्य थ्रेड को उसी ऑब्जेक्ट को लॉक करने के लिए इंतजार करना पड़ता है।

  • synchronized(this) वर्तमान थ्रेड के लिए उदाहरण this का ताला प्राप्त कर लेता है। विधि विभिन्न उदाहरणों (इसके लिए अलग-अलग मानों और इसलिए अलग-अलग ताले) पर समानांतर चल सकती है

  • synchronized(SomeClass.class) कुछ क्लास के वैश्विक वर्ग ऑब्जेक्ट के लॉक को प्राप्त करता है। विधि का केवल एक उदाहरण चलाया जा सकता है क्योंकि सभी ऑब्जेक्ट इंस्टेंस एक ही वैश्विक ऑब्जेक्ट (उसी लॉक) पर लॉक होते हैं।

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