34

जावा में एक सिंक्रनाइज़ विधि और सिंक्रनाइज़ ब्लॉक के बीच क्या अंतर है?जावा में एक सिंक्रनाइज़ विधि और सिंक्रनाइज़ ब्लॉक के बीच क्या अंतर है?

मैं नेट पर जवाब खोज रहे होते हैं, लोगों को इस एक :-(के बारे में इतना अनिश्चित होने लगते हैं

मेरे ले होगा दोनों के बीच कोई अंतर नहीं है, सिवाय इसके कि सिंक ब्लॉक अधिक हो सकता है, नहीं है दायरे में स्थानीय और इसलिए ताला कम समय के लिए किया जाएगा ??

और एक स्थिर पद्धति पर ताला के मामले में, क्या ताला लिया जाता है पर क्या कक्षा पर एक लॉक का अर्थ है?

+0

@ कोशिश-पकड़ने के अंत में वह इस सवाल का डुप्लिकेट नहीं है; वह प्रश्न पूछता है कि क्या एक सिंक्रनाइज़ विधि केवल विधि, या संपूर्ण वस्तु के लिए विशेष पहुंच प्रदान करती है। –

+0

@MarkRotteveel आप अलग-अलग खिताब के मामले में सही हैं। दूसरी तरफ, अन्य प्रश्नों के उत्तरों में अंतर भी शामिल हैं: सिंक्रनाइज़ किए गए सेक्शन को कुछ कथन (या नहीं) में स्कॉप करना और इसे लॉक करना है (या उस पर कोई नियंत्रण नहीं है) को नियंत्रित करना। –

उत्तर

44

एक सिंक्रनाइज़ विधि विधि रिसीवर को लॉक के रूप में उपयोग करती है (यानी। गैर स्थैतिक तरीकों के लिए this, और स्थैतिक विधियों के लिए संलग्न वर्ग)। Synchronized ब्लॉक अभिव्यक्ति को लॉक के रूप में उपयोग करता है।

तो निम्नलिखित दो तरीकों भावी लॉक होने से बराबर हैं:

synchronized void mymethod() { ... } 

void mymethod() { 
    synchronized (this) { ... } 
} 

स्थिर तरीकों के लिए, वर्ग लॉक कर दिया जाएगा:

class MyClass { 
    synchronized static mystatic() { ... } 

    static mystaticeq() { 
    syncrhonized (MyClass.class) { ... } 
    } 
} 

सिंक्रनाइज़ ब्लॉकों के लिए, यदि आप किसी भी गैर null उपयोग कर सकते हैं ऑब्जेक्ट लॉक के रूप में:

synchronized (mymap) { 
    mymap.put(..., ...); 
} 

लॉक स्कोप

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

+0

मैंने कुछ समय पहले (स्रोत खो दिया) पढ़ा है कि ब्लॉक पर सिंक्रनाइज़ किए जाने से विधि पर सिंक्रनाइज़ किया जा सकता है, भले ही वह ब्लॉक पूरे विधि निकाय को समाहित करता हो। कोशिश करने के लिए दिलचस्प माइक्रो बेंचमार्क हो सकता है। –

+1

लॉक स्कोप में, आपको शायद "... सिंक्रनाइज़ किए गए ब्लॉक में, लॉक सिंक्रनाइज़ किए गए ब्लॉक के दौरान ही आयोजित किया जाता है" और नहीं "... सिंक्रनाइज़ विधि में लॉक सिंक्रनाइज़ किए गए ब्लॉक के दौरान ही होता है" – mrvincenzo

+2

@ ग्रेगरी मोस्टिज्की इस आलेख के अनुसार, एक सिंक्रनाइज़ किए गए ब्लॉक की तुलना में JVM एक सिंक्रनाइज़ विधि के लिए कम बाइटकोड बनाता है। http://www.ibm.com/developerworks/java/library/j-5things15/index.html?ca=drs- –

3

हाँ , यह एक अंतर है। दूसरा यह है कि आप अन्य वस्तुओं पर this से लॉक प्राप्त कर सकते हैं।

8

एक सिंक्रनाइज़ विधि शॉर्टेंड है। यह: तो वास्तव में

class Something { 
    public void doSomething() { 
     synchronized(this) { 
      ... 
     } 
    } 

    public static void doSomethingStatic() { 
     synchronized(Something.class) { 
      ... 
     } 
    } 
} 

(कहाँ Something.class वर्ग Something के लिए वर्ग वस्तु है।)

, एक साथ:

class Something { 
    public synchronized void doSomething() { 
     ... 
    } 

    public static synchronized void doSomethingStatic() { 
     ... 
    } 
} 

, सभी इरादों और उद्देश्यों के लिए है, इस के बराबर सिंक्रनाइज़ ब्लॉक, आप अपने लॉक के बारे में अधिक विशिष्ट हो सकते हैं, और जब आप इसका उपयोग करना चाहते हैं तो अधिक बढ़िया हो सकता है, लेकिन इसके अलावा कोई फर्क नहीं पड़ता। वस्तु दृष्टान्त पर

0

एक सिंक्रनाइज़ विधि ताले विधि में निहित है

कहाँ के रूप में एक तुल्यकालन ब्लॉक किसी भी वस्तु पर लॉक कर सकते हैं -। आम तौर पर एक म्युटेक्स obect एक उदाहरण चर के रूप में परिभाषित किया। यह ताले के संचालन में अधिक नियंत्रण की अनुमति देता है।

2

मुख्य अंतर यह है: यदि आप सिंक्रनाइज़ करने के लिए एक विधि घोषित करते हैं, तो विधि का पूरा शरीर सिंक्रनाइज़ हो जाता है; यदि आप सिंक्रनाइज़ किए गए ब्लॉक का उपयोग करते हैं, तो, आप सिंक्रनाइज़ किए गए ब्लॉक में विधि के "महत्वपूर्ण खंड" को घेर सकते हैं, जबकि ब्लॉक के बाकी तरीके को छोड़कर।

यदि संपूर्ण विधि महत्वपूर्ण खंड का हिस्सा है, तो प्रभावी रूप से कोई अंतर नहीं है। यदि ऐसा नहीं है, तो आपको केवल महत्वपूर्ण अनुभाग के आसपास एक सिंक्रनाइज़ ब्लॉक का उपयोग करना चाहिए। सिंक्रनाइज़ किए गए ब्लॉक में आपके जितने अधिक बयान हैं, उतनी ही कम समांतरता आपको मिलती है, इसलिए आप उन्हें न्यूनतम रखना चाहते हैं।

+0

त्वरित अनुवर्ती: क्या इसका मतलब यह होगा कि एक सिंक्रनाइज़ किए गए ब्लॉक को सिंक्रनाइज़ विधि से उपयोग करने के लिए कम महंगा है ? – Everyone

+0

यदि सिंक्रनाइज़ किए गए ब्लॉक में फ़ंक्शन की सभी सामग्री शामिल है, तो कोई अंतर नहीं है। हालांकि, यदि आप सिंक्रनाइज़ किए गए ब्लॉक का उपयोग करते हैं, तो आप केवल महत्वपूर्ण अनुभाग को घेर सकते हैं (शायद सिंक्रनाइज़ किए गए क्षेत्र से कुछ गणना को छोड़कर)। यदि आप ऐसा करते हैं, तो आपका प्रोग्राम तेजी से चल जाएगा। –

0

मेरा लेना दोनों के बीच कोई अंतर नहीं होगा, सिवाय इसके कि सिंच ब्लॉक को क्षेत्र में अधिक स्थानीयकृत किया जा सकता है और इसलिए लॉक कम समय का होगा ??

हां। तुम सही हो। synchronized विधियों के विपरीत, सिंक्रनाइज़ किए गए बयानों को उस वस्तु को निर्दिष्ट करना होगा जो आंतरिक लॉक प्रदान करता है। जावा ट्यूटोरियल से

उदाहरण:

public void addName(String name) { 
    synchronized(this) { 
     lastName = name; 
     nameCount++; 
    } 
    nameList.add(name); 
} 

सिंक्रनाइज़ बयान भी सुक्ष्म तुल्यकालन के साथ संगामिति में सुधार के लिए उपयोगी होते हैं। आप नीचे उपयोग मामले के लिए एक ही ट्यूटोरियल पेज पर अच्छा उदाहरण पा सकते हैं।

मान लीजिए, उदाहरण के लिए, कक्षा MsLunch में दो उदाहरण फ़ील्ड, सी 1 और सी 2 हैं, जिनका कभी भी उपयोग नहीं किया जाता है। इन फ़ील्ड के सभी अपडेट synchronized होना चाहिए, लेकिन सी 1 के अपडेट के साथ सीएल के अपडेट को रोकने से रोकने का कोई कारण नहीं है - और अनावश्यक अवरोधन बनाकर ऐसा करने से समरूपता कम हो जाती है। सिंक्रनाइज़ किए गए तरीकों का उपयोग करने या अन्यथा इसके साथ जुड़े लॉक का उपयोग करने के बजाय, हम ताले प्रदान करने के लिए पूरी तरह से दो ऑब्जेक्ट्स बनाते हैं।

और एक स्थिर विधि पर लॉक के मामले में, लॉक क्या लिया जाता है? क्लास पर लॉक का अर्थ क्या है?

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

जब आप के रूप में synchronized (गैर static) एक विधि बनाने:

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

यदि आप कर static synchronized के रूप में एक विधि:

यह एक ही कक्षा के विभिन्न वस्तुओं पर static synchronized तरीकों में से दो आमंत्रण बिछा करने के लिए संभव नहीं है। जब एक धागा कक्षा ए के किसी ऑब्जेक्ट के लिए static synchronized विधि निष्पादित कर रहा है, तो अन्य सभी थ्रेड जो क्लास ए ब्लॉक (निष्पादन को निलंबित करते हैं) के किसी भी ऑब्जेक्ट पर static synchronized विधियों का उपयोग करते हैं, जब तक कि पहला थ्रेड विधि निष्पादन के साथ नहीं किया जाता है।

आप इस एसई प्रश्न में तुल्यकालन के लिए बेहतर विकल्प खोजने:

Avoid synchronized(this) in Java?

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