2011-03-14 13 views
7

मान लीजिए कि मैं synchronized कुछ थ्रेड के अंदर कोड के ब्लॉक को निष्पादित कर रहा हूं और synchronized ब्लॉक में मैं एक ऐसी विधि को कॉल करता हूं जो कोड के एक सिंक्रनाइज़ किए गए ब्लॉक को संसाधित करने के लिए एक और धागा उत्पन्न करता है जिसके लिए पहली विधि के समान लॉक की आवश्यकता होती है । तो छद्म जावा कोड में:जावा थ्रेड्स और सिंक्रनाइज़ ब्लॉक

public void someMethod() { 
    synchronized(lock_obj) { 
    // a whole bunch of stuff... 

    // this is the last statement in the block 
    (new Thread(someOtherMethod())).start(); 
    } 
    // some more code that doesn't require a lock 
} 

public void someOtherMethod() { 
    // some setup code that doesn't require a lock 

    // return the stuff we want to run in another thread 
    // that does require a lock 
    return new Runnable() { 
    @Override 
    public void run() { 
     synchronized(lock_obj) { 
     // some more code 
     } 
    } 
    }; 
} 

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

उत्तर

8

आप अभी भी रननेबल और धागे के निर्माण के दौरान ताला लगा रहे हैं, लेकिन जब आप कॉल शुरू करते हैं और धागे वास्तव में उठाते हैं तो आप लॉक को छोड़ रहे हैं। नए थ्रेड को अन्य धागे के साथ लॉक के लिए प्रतिस्पर्धा करना होगा।

5

इस कोड के बारे में कुछ भी गलत नहीं है। someOtherMethod() में वापसी विवरण से पहले, कोड someMethod() के सिंक्रनाइज़ किए गए ब्लॉक में चल रहा है। नए धागे के शुरू होने के बाद, run() विधि के अंदर synchronized कथन पर यह lock_obj पर लॉक प्राप्त होने तक (जल्द से जल्द, जब भी someMethod() इसके सिंक्रनाइज़ किए गए ब्लॉक से बाहर निकलता है) पर ब्लॉक करेगा।

+0

बस कुछ ऐसा जो कुछ याद किया जा सकता है - सिंक्रनाइज़ किया गया ब्लॉक कुछ मोड() में सिंक्रनाइज़ किया गया है जैसे ही प्रारंभ() कहा जाता है, और नया धागा समानांतर निष्पादित होता है। ऐसा लगता है कि ओपी के भ्रम के कारण क्या हुआ। –

+0

@ अब्राहम फिलिप - मैं इसे इस तरह से नहीं रखूंगा। 'प्रारंभ()' कहा जाता है जब सिंक्रनाइज़ ब्लॉक _not_ exited है। (यह बाद में बहुत ही कम समय से बाहर निकलता है, क्योंकि 'प्रारंभ() 'को कॉल सिंक्रनाइज़ किए गए ब्लॉक में अंतिम विवरण होता है।) इसके बजाय,' start() 'को कॉल करने से दूसरे थ्रेड के निष्पादन की शुरुआत होती है (जो मॉनीटर के साथ शुरू होता है आयोजित), 'RunOable' में कोड चला रहा है 'कुछ अन्य विधि()' द्वारा लौटाया गया। उस अन्य धागे को अपने स्वयं के सिंक्रनाइज़ किए गए ब्लॉक में प्रवेश करने से पहले बाहर निकलने के लिए 'कुछ विधि()' में ब्लॉक के लिए प्रतीक्षा करने की आवश्यकता है। –

+0

क्षमा करें, आप बिल्कुल सही हैं। मुझे दोबारा दोहराएं, "ठीक बाद" शुरू करें() को बुलाया जाता है। मैं बस इसे हाइलाइट करना चाहता था क्योंकि ओपी सोच रहा था कि दूसरा थ्रेड रननेबल पहले सिंक्रनाइज़ ब्लॉक के भीतर निष्पादित कर रहा था (जैसा कि यहां एक उत्तर ने गलती से दावा किया है http://stackoverflow.com/a/5295252/3000919)। मेरा मानना ​​है कि आपकी टिप्पणी बताती है कि बहुत अच्छी तरह से, धन्यवाद :) –

-2

अगर कुछ विधि() पहले आक्रमण किया जाता है, तो यह डेडलॉक का शास्त्रीय उदाहरण है।

क्या मैंने कानूनी भी लिखा है?
---- हां यह पूरी तरह से कानूनी रूप से कानूनी है।

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

+1

यह एक डेडलॉक क्यों है? Thread.start तुरंत लौटता है और उस बिंदु पर lock_obj पर लॉक जारी किया जाता है जिस बिंदु पर चलने योग्य रननेबल या तो लॉक उठाता है या इसे रिलीज़ करने के लिए किसी अन्य थ्रेड पर इंतजार करता है। – davidk01

+1

@ davidk01 से सहमत हैं कि यह एक डेडलॉक नहीं है। और यह निश्चित रूप से 'शास्त्रीय' उदाहरण नहीं है यदि यह था। बस आगे की जानकारी के लिए, थ्रेड शुरू होने के बावजूद, जावा में एक विधि को कॉल करना जो उसी लॉक पर सिंक्रनाइज़ किया गया है, पहले से ही मौजूद थ्रेड को अवरुद्ध नहीं किया जाएगा, क्योंकि कॉलर पहले से ही लॉक का मालिक है। – Sogger

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