2013-05-26 5 views
12

में वापस पाने के यह एक वकालत प्रतिमान कि इंतजार() एक तुल्यकालन ब्लॉक के अंदर थोड़ी देर के पाश अंदर लागू किया जाना चाहिए।इंतजार कैसे करता है() ताला जावा

मेरे सवाल यह है कि प्रतीक्षा() धागा ताला वापस पाने के है?

// Thread 1 
    synchronized (mon) { 
    while (!condition) 
      mon.wait(); 

    // Do something 
    } 

//Thread 2 
    synchronized (mon) {//set condition appropriately 
      mon.notify(); 
    } 

धागे को पहले 1 रन पर विचार करें और स्थिति की प्रतीक्षा करना शुरू करें। यह लॉक जारी करता है और थ्रेड 2 लॉक को स्थिति सेट करता है और थ्रेड को सूचित करता है 1. अब थ्रेड 1 लॉक हो जाता है, स्थिति की जांच करता है और "कुछ करें" निष्पादित करना शुरू करता है।

मेरा प्रश्न यह है कि जब थ्रेड 1 अधिसूचित किया जाता है तो यह समय की स्थिति से निष्पादन शुरू करता है, सिंक्रनाइज़ (सोम) कोड की रेखा को फिर से निष्पादित नहीं किया जाता है तो थ्रेड 1 लॉक कैसे प्राप्त करता है? आंतरिक गतिशीलता क्या हैं जो लॉक को थ्रेड 1 पर वापस देती हैं?

उत्तर

7

जब Thread1 धागा अधिसूचित किया गया है ताला प्राप्त करने के लिए इससे पहले कि यह इंतजार विधि निकल सकते हैं, के लिए वस्तु # इंतजार जावा दस्तावेज़ नहीं देख है:

धागा T तो इस के लिए प्रतीक्षा सेट से निकाल दिया जाता है ऑब्जेक्ट और थ्रेड शेड्यूलिंग के लिए पुनः सक्षम। इसके बाद ऑब्जेक्ट पर सिंक्रनाइज़ करने के अधिकार के लिए सामान्य तरीके से अन्य धागे के साथ प्रतिस्पर्धा करता है; एक बार जब यह ऑब्जेक्ट का नियंत्रण प्राप्त कर लेता है, तो उसके सभी ऑब्जेक्ट पर सिंक्रनाइज़ेशन दावों को स्थिति एंटी स्थिति में बहाल कर दिया जाता है - यानी स्थिति के अनुसार wait विधि लागू की गई थी। थ्रेड T तो wait विधि के मंगलाचरण से वापस आती है। इस प्रकार, wait विधि से वापस लौटने पर, ऑब्जेक्ट की सिंक्रनाइज़ेशन स्थिति और थ्रेड T ठीक उसी तरह है जब wait विधि लागू हुई थी।

+0

+1। –

+0

@ नाथन: मुझे लगता है कि हम जवाब जानते हैं :-) हम जावा डॉक के इस हिस्से को नहीं (कम से कम मुझे समझ में नहीं आता): इस प्रकार, * {@code प्रतीक्षा} विधि से वापस लौटने पर, सिंक्रनाइज़ेशन ऑब्जेक्ट की स्थिति और * थ्रेड {@code टी} ठीक उसी तरह है जब {@code प्रतीक्षा} विधि * लागू की गई थी। – Geek

+0

@ गीक: आप क्या समझते नहीं हैं? प्रतीक्षा विधि से निकलने से थ्रेड को एक सिंक्रनाइज़ ब्लॉक में रखा जाता है, इसलिए इसे पहले लॉक प्राप्त करने की आवश्यकता होती है। अन्यथा यह लॉक प्राप्त किए बिना सिंक्रनाइज़ किए गए ब्लॉक में कोड निष्पादित करेगा। –

7

synchronized(mon) एक अभिव्यक्ति नहीं है जिसे निष्पादित किया जाना है।

यह स्रोत कोड में एक वाक्यविन्यास तत्व है जो संकलक (और फिर रनटाइम) को बताता है कि कोड के लिपटे अनुभाग को केवल mon से जुड़े लॉक के बाद वर्तमान थ्रेड द्वारा अधिग्रहित किया जाना चाहिए, भले ही आप सिंक्रनाइज़ किए गए ब्लॉक से पहले कोड की रेखा "से" न आएं।

wait() अवरोध समाप्त, और लौटने से पहले यह पुनः प्राप्त करना होगा।

+0

आपका उत्तर बिल्कुल सही है। क्या आप मुझे बता सकते हैं कि यह मेटाडेटा जानकारी रन टाइम पर कैसे काम करती है। क्या आप मुझे कुछ संसाधनों पर इंगित कर सकते हैं जहां मैं इसके बारे में पढ़ सकता हूं। – Geek

+0

मुझे लगता है कि आप जो [JVM विनिर्देश] में देख रहे हैं उसे ढूंढ सकते हैं (http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.11.10), लेकिन मैंने उन्हें कभी नहीं पढ़ा है। –

+1

कॉलिंग प्रतीक्षा JVM को सूचित करता है कि लॉक प्राप्त करने वाला थ्रेड इसे छोड़ना चाहता है। इसका जेवीएम जो थ्रेड को प्रतीक्षा कतार में रखता है और लॉक जारी करता है। जब सूचित करें (सभी) को बुलाया जाता है तो सिग्नल JVM को भेजा जाता है कि थ्रेड जो लॉक प्राप्त करता है (जिसका अधिसूचना (सभी) कहा जाता है) ने लॉक जारी किया है और कोई भी योग्य उम्मीदवार (जो कि जेवीएम द्वारा प्रतीक्षा कतार में हैं)) लॉक प्राप्त करने के लिए जेवीएम द्वारा चुना गया है। नियंत्रण प्रवाह को समझने के लिए इस लिंक को देखें http://booxs.biz/images/java/thread-states.png – Saurabh

0

थ्रेड 1 अधिसूचित होने के बाद, इसे तुरंत लॉक मिला और // कुछ चलाने के लिए शुरू करें।

जब थ्रेड 1 इंतजार, यह सिर्फ अस्थायी रूप से अवरोध खोल, और जब धागा अधिसूचित किया गया है, यह ताला फिर से प्राप्त कर सकते हैं और सिंक्रनाइज़ चला की जरूरत नहीं है (...)।

0
// Thread 1 
synchronized (mon) { 
Systemout.println("I am invoked!"); 
while (!condition) 
     mon.wait(); 

// Do something 
} 

//Thread 2 
synchronized (mon) {//set condition appropriately 
     mon.notify(); 
} 

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

अगर मेरे सही ढंग से निम्नलिखित को समझने:

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

लाइन Systemout.println ("मुझे आह्वान किया गया है!"); निष्पादित नहीं किया जाएगा, "इस प्रकार, प्रतीक्षा विधि से वापस आने पर, ऑब्जेक्ट की सिंक्रनाइज़ेशन स्थिति और थ्रेड टी ठीक उसी तरह है जब प्रतीक्षा विधि लागू की गई थी।"

क्या मैं सही हूँ? Javadoc अंश के लिए

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