2009-07-09 18 views
11

कृपया थोड़ी सी सहायता, कृपया नीचे दिए गए कोड पर विचार करें।पुनर्वित्त लॉकिंग

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

public class LoggingWidget extends Widget { 
    public synchronized void doSomething() { 
     System.out.println(toString() + ": calling doSomething"); 
     super.doSomething(); 
    } 
} 

मैंने पढ़ा है कि जब LoggingWidget में DoSomething() कहा जाता है, JVM विजेट पर पहले और उसके बाद LoggingWidget पर एक ताला प्राप्त करने के लिए कोशिश करेंगे।

मुझे कारण जानने के लिए उत्सुकता है। ऐसा इसलिए है क्योंकि JVM जानता है कि DoSomething() के पास super.do कुछ() है या एक उपclass विधि को कॉल करने के लिए हमेशा सुपरक्लास पर लॉक प्राप्त होगा।

चीयर्स

+0

आपको इसे पढ़ने के लिए एक संदर्भ पोस्ट करना चाहिए क्योंकि यह सच नहीं है :-) –

+0

वास्तव में आपकी मदद के लिए धन्यवाद। मैंने पुनर्वित्त लॉकिंग के स्पष्टीकरण को गलत समझा।अपनी व्याख्या पढ़ने के बाद, मैं स्रोत पर वापस गया (अभ्यास में कॉन्सुरेंसी पुस्तक से एक अंश) और अब यह समझ में आता है। – CaptainHastings

उत्तर

9

आप गलत कर रहे हैं - ताले उदाहरण स्तर पर प्राप्त कर रहे हैं।

Widget w = new LoggingWidget 

आप ताले अलग-अलग होने के रूप में (यह भी पर नज़र रखता है, mutexes या संकेतबाहु के रूप में जाना जाता है) देख सकते हैं ": आपके उदाहरण में केवल एक ही ताला केवल एक ही बनाया उदाहरण है, क्योंकि जब आप कहते हैं है संलग्न "प्रत्येक ऑब्जेक्ट उदाहरण JVM में।

यदि आपके पास विधि LoggingWidget उपclass पर विधि थी, तो आप इसे सत्य मानेंगे। एक ही समय में [नई) विधि और doSomething विधि को कॉल करना संभव नहीं होगा [उसी ऑब्जेक्ट पर विभिन्न धागे के साथ]।

यह सुपरक्लास पर अन्य synchronized विधि के लिए भी सच है (यानी यह ओवरराइड किए जाने वाले तरीकों से किसी भी तरह से प्रभावित नहीं होता है)।

1

लॉक पाने के लिए केवल एक उदाहरण है, LoggingWidget का उदाहरण, Widget का वास्तविक उदाहरण कभी नहीं होता है।

लॉक प्राप्त होता है जब आप LoggingWidget.doSomething() पर कॉल करते हैं और जब आप super.doSomething() पर कॉल करते हैं तो आपके पास पहले से ही लॉक होता है, विधि को सामान्य के रूप में निष्पादित किया जाता है।

public void doSomething() { 
    synchronized (this) { 
     System.out.println(toString() + ": calling doSomething"); 
     super.doSomething(); 
    } 
} 

आप उदाहरण के लिए, नहीं वर्ग पर ताला लगा रहे हैं:

+0

धन्यवाद निक, समझ में आता है। – CaptainHastings

5
public synchronized void doSomething() { 
    System.out.println(toString() + ": calling doSomething"); 
    super.doSomething(); 
} 

एक ही रूप है। तो जब super.do कुछ() कहा जाता है, तो आपके पास पहले से ही उस उदाहरण को बंद कर दिया गया है।

+0

धन्यवाद, जैसा कि गीत जाता है, मैं अब स्पष्ट रूप से देख सकता हूं ... – CaptainHastings

0

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

0

बीगोएट्ज़ - "जेजेवा कंसुरेंसी इन प्रैक्टिस" अगर आंतरिक ताले पुनर्वित्त नहीं थे, तो सुपर कॉल करने के लिए कॉल कुछ कुछ भी लॉक हासिल करने में सक्षम नहीं होगा क्योंकि इसे पहले से ही माना जाएगा, और धागा स्थायी रूप से इंतजार कर रहा है एक ताला के लिए यह कभी हासिल नहीं कर सकता है। पुनर्वित्त हमें इस तरह की स्थितियों में डेडलॉक से बचाता है।

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