2010-07-01 18 views
31

मेरे पास कक्षा में 4 विधियां हैं (m1, m2, m3 और m4)। विधि m1, m2 और m3synchronized विधियां हैं। इसके अलावा, मेरे पास 4 धागे t1, t2, t3 और t4 क्रमशः हैं।दो सिंक्रनाइज़ किए गए विधियों को एक साथ निष्पादित करें

तो t1 पहुँच m1 विधि (सिंक्रनाइज़ विधि), t2 धागा पहुँच m2 विधि एक साथ (विधि सिंक्रनाइज़) कर सकता है? यदि नहीं तो टी 2 की स्थिति क्या होगी?

उत्तर

42

t1 पहुँच एम 1 विधि (सिंक्रनाइज़ विधि), t2 धागा पहुँच एम 2 विधि (सिंक्रनाइज़ विधि) कर सकता है एक साथ?

synchronized कीवर्ड वस्तु स्तर, और केवल एक धागे पर लागू होता है वस्तु का ताला पकड़ कर सकते हैं। तो जब तक आप एक ही ऑब्जेक्ट के बारे में बात कर रहे हों, तब कोई, t2t1 के लिए m1 दर्ज किए गए लॉक को रिलीज़ करने के लिए प्रतीक्षा करेगा।

धागा हालांकि विधि से लौट रहे, Object.wait() फोन करके बिना अवरोध खोल सकते हैं।

यदि नहीं, तो टी 2 की स्थिति क्या होगी?

यह तंग बैठते हैं और t1 के लिए प्रतीक्षा (विधि से वापसी या Object.wait() आह्वान) ताला जारी करने के लिए होगा। विशेष रूप से, यह BLOCKED state में होगा।

एक थ्रेड के लिए थ्रेड स्थिति मॉनिटर लॉक के लिए प्रतीक्षा अवरुद्ध है। अवरुद्ध स्थिति में एक थ्रेड एक मॉनिटर लॉक के लिए एक सिंक्रनाइज़ ब्लॉक/विधि दर्ज करने या Object.wait पर कॉल करने के बाद एक सिंक्रनाइज़ ब्लॉक/विधि को पुन: प्रस्तुत करने का इंतजार कर रहा है।

नमूना कोड:

public class Test { 

    public synchronized void m1() { 
     try { Thread.sleep(2000); } 
     catch (InterruptedException ie) {} 
    } 

    public synchronized void m2() { 
     try { Thread.sleep(2000); } 
     catch (InterruptedException ie) {} 
    } 

    public static void main(String[] args) throws InterruptedException { 
     final Test t = new Test(); 
     Thread t1 = new Thread() { public void run() { t.m1(); } }; 
     Thread t2 = new Thread() { public void run() { t.m2(); } }; 

     t1.start(); 
     Thread.sleep(500); 

     t2.start(); 
     Thread.sleep(500); 

     System.out.println(t2.getState()); 
    } 
} 

आउटपुट:

BLOCKED 
+0

पर दिखाई दे रहे हैं, लेकिन अगर हम ऐसा कुछ करते हैं तो क्या? अंतिम टेस्ट tt1 = नया टेस्ट(); अंतिम टेस्ट tt2 = नया टेस्ट(); थ्रेड टी 1 = नया थ्रेड() {सार्वजनिक शून्य रन() {tt1.m1(); }}; थ्रेड टी 2 = नया थ्रेड() {सार्वजनिक शून्य रन() {tt2.m2(); }}; – Prem

+0

मैं एक ही चीज़ चलाता हूं और मुझे आउटपुट के रूप में TIMED_WAIT मिल गया .... – Prem

+0

@aioobe सिंक्रनाइज़ कोड ब्लॉक (विधियों नहीं) के मामले में क्या होता है। क्या दो थ्रेड एक ही ऑब्जेक्ट के दो अलग-अलग सिंक्रनाइज़ कोड ब्लॉक को समवर्ती रूप से एक्सेस कर सकते हैं? – yuva

11

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

इस मामले में अवरुद्ध धागे की वास्तविक राज्य, के रूप में JConsole द्वारा रिपोर्ट, हो जाएगा की तरह java.lang.Thread.State: WAITING (on object monitor)

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

// Thread 1 
A a1 = new A(); 
a1.m1(); 

// Thread 2 
A a2 = new A(); 
a2.m2() 

तो इस मामले में, दूसरा धागा विधि कॉल करने में सक्षम है, क्योंकि यह a2 वस्तु है, जो नहीं है की अंतर्निहित मॉनिटर प्राप्त करने के लिए कोशिश कर रहा है हो जाएगा थ्रेड 1 द्वारा लॉक किया गया। लेकिन अगर थ्रेड 2 ने a1.m2() पर कॉल करने का प्रयास किया, तो यह तब तक अवरुद्ध होगा जब तक थ्रेड 1 ने m1() निष्पादित नहीं किया था।

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

+0

दरअसल, यह ब्लॉक राज्य में होगा, न कि प्रतीक्षा राज्य। – aioobe

+0

उपर्युक्त उदाहरण में 'a2.m2()' को कॉल करना थोड़ा भ्रामक है। चूंकि 'ए 1' और' ए 2 'कक्षा' ए' के विभिन्न उदाहरण हैं, प्रत्येक के पास अपना 'लॉक' है। इसलिए, यहां तक ​​कि 'a1.m1()' और 'a2.m1()' को भी निष्पादित किया जा सकता है। – derenio

+0

@derenio - वह उस बिंदु पर बना था जो मैं उस अनुभाग में बना रहा था, जो बोल्ड किए गए कथन के आधार पर आगे बढ़ रहा था। और चूंकि सवाल यह पूछ रहा है कि 'm1' और' m2' को एक बार में बुलाया जा सकता है, उदाहरण के लिए मैं यही अटक गया हूं। –

4

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

1

तो t1 पहुँच एम 1 विधि (सिंक्रनाइज़ विधि), (एक पर्याप्त आधुनिक JVM के साथ आप वास्तव में इस राज्य कंसोल पर प्रदर्शित करता है, तो आप सही तरीके से पूछना हो सकता है।) धागा पहुँच एम 2 विधि t2 सकता है (सिंक्रनाइज़ विधि) एक साथ?

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

ताले synchronized तरीके

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

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

अपने दूसरे प्रश्न के वापस आ रहा है की वजह से किया गया था होती है:

यदि नहीं, तो क्या t2 के राज्य हो सकता है?

थ्रेड टी 2 अवरुद्ध राज्य में है और लॉक को रिलीज़ करने के लिए थ्रेड टी 1 की प्रतीक्षा कर रहा है।

से जावा documentation पेज:

synchronized विधि बनाने दो प्रभाव है।

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

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

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