2015-07-27 11 views
18

इस कोड पर विचार करें:जावा सिंक्रनाइज़ विधि

public synchronized void onSignalsTimeout(List<SignalSpec> specs) { 
    if (specs != null && specs.size() > 0) { 
     for (SignalSpec spec : specs) { 
      ParsedCANSignal timeoutedSignal = new ParsedCANSignal(); 
      SignalsProvider.getInstance().setSignal(spec.name, spec.parent.parent.channel, timeoutedSignal); 
     } 
    } 
} 

मैं साधारण सवाल है: जब थ्रेड विधि onSignalsTimeout 1 कॉल, 2 का उपयोग वस्तुओं है कि उस विधि में पहुंचा जा सकता है थ्रेड कर सकते हैं?

कहीं भी यदि 'सिंक्रनाइज़' इस विधि या इस विधि में इस्तेमाल सभी वस्तुओं के लिए उपयोग करने के लिए केवल पहुँच ताले नहीं मिल सकी।

उत्तर

49

पहले, सिंक्रनाइज़ तरीकों के बारे में भूल जाते हैं। एक तथाकथित समन्वयित विधि ...

synchronized AnyType foobar(...) { 
    doSomething(); 
} 

लेकिन इस लेखन के लिए एक शॉर्टकट रास्ता कुछ भी नहीं है:

AnyType foobar(...) { 
    synchronized(this) { 
     doSomething(); 
    } 
} 

या तो मामले में विधि के बारे में विशेष कुछ भी नहीं है। क्या खास है सिंक्रनाइज़ ब्लॉक है, और क्या एक तुल्यकालन ब्लॉक करता है बहुत सरल है। जब JVM इस कार्यान्वित:

synchronized(foo) { 
    doSomething(); 
} 

यह पहली बार अभिव्यक्ति foo मूल्यांकन करता है। परिणाम एक ऑब्जेक्ट संदर्भ होना चाहिए। फिर यह ऑब्जेक्ट लॉक करता है, synchronized ब्लॉक का शरीर निष्पादित करता है, और फिर यह ऑब्जेक्ट को अनलॉक करता है।

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

धागा कुछ समय धागा पहले से ही foo बंद कर दिया गया है (उसी synchronized ब्लॉक में, या एक अलग से एक में) synchronized(foo) {...} दर्ज करने के लिए, तो थ्रेड धागा रिलीज ताला तक इंतजार करने के लिए मजबूर हो जाएगा की कोशिश करता है।


आप synchronized ब्लॉक का उपयोग डेटा की रक्षा के लिए।

मान लीजिए कि आपके प्रोग्राम में ऑब्जेक्ट्स का कुछ संग्रह है जो अलग-अलग राज्य में हो सकता है। मान लीजिए कि कुछ राज्य समझ में आते हैं, लेकिन ऐसे अन्य राज्य हैं जो समझ में नहीं आते- अमान्य राज्य।

मान लीजिए कि किसी थ्रेड के लिए किसी वैध स्थिति से डेटा को अस्थायी रूप से अमान्य स्थिति बनाने के बिना किसी वैध स्थिति से डेटा को बदलने के लिए संभव नहीं है।

आप कोड है कि एक synchronized(foo) ब्लॉक में राज्य में परिवर्तन कर दिया है, और आप कोड के हर ब्लॉक कि राज्य देख सकते हैं एक तुल्यकालन ब्लॉक कि एक ही वस्तु, foo ताले में तो आप शब्दों में कहें, तो अस्थायी अमान्य स्थिति को देखने से अन्य धागे को रोक देगा।

+2

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

+0

@arenaq _Where?_ डीबगर आपको क्या दिखाएगा? मुझे नहीं पता। मैंने डिबगर्स में ज्यादा जावा कोड नहीं देखा है। मैं एक सी प्रोग्रामर हूँ। सिंक्रनाइज़ेशन सी में एक आंतरिक भाषा सुविधा नहीं है, इसलिए सी में, डीबगर दिखाता है कि थ्रेड को सिंक्रनाइज़ेशन सिस्टम कॉल में बंद कर दिया गया है, कॉल के अंदर से सिंक्रनाइज़ेशन लाइब्रेरी फ़ंक्शन में, मेरे कोड में कहीं से। जावा डिबगर्स जो मैंने उपयोग किया है, वे सिस्टम कॉल या जेवीएम की आंतरिक कार्यप्रणाली नहीं दिखाते हैं, और मुझे कभी भी जावा थ्रेड के ढेर का निरीक्षण नहीं करना पड़ता है जो लॉक प्राप्त करने का इंतजार कर रहा था। –

+0

इसे भूल जाओ, इसके असंबद्ध प्रश्न वैसे भी ... एक नया विषय होना चाहिए। – arenaq

3

इस संदर्भ में, synchronized साथ ही इस विधि को लॉक करता है और आपकी कक्षा में synchronized जैसी अन्य विधि भी चिह्नित की जाती है।

+0

तो मूल रूप से, यदि मेरे पास एक डेटा संरचना तक पहुंचने के लिए 2 सिंक्रनाइज़ किए गए तरीके होंगे और एक थ्रेड से दूसरे को और दूसरे को दूसरे थ्रेड से बुलाया जाएगा, तो सिंक्रनाइज़ पूरी तरह से बेकार होगा? – arenaq

+0

आप * चीजें व्यवस्थित कर सकते हैं ताकि डेटा संरचना को केवल एक फ़ंक्शन को कॉल करके एक्सेस किया जा सके, जिसे आप * सिंक्रनाइज़ * के रूप में चिह्नित करते हैं। – Bathsheba

+0

यदि 2 विधियों को 'सिंक्रनाइज़ किया गया' चिह्नित किया गया है, तो 'thread1'' method1' तक नहीं पहुंच सकता है जबकि 'thread2'' method2' निष्पादित कर रहा है? – Codebender

5

हाँ, अन्य थ्रेड विधि में इस्तेमाल किया वस्तुओं का उपयोग कर सकते हैं; सिंक्रनाइज़ किए गए कीवर्ड गारंटी देता है कि उस समय एक से अधिक धागे विधि के कोड को निष्पादित नहीं कर सकते हैं।

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html से:

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

लेकिन मैं अभी भी ऑब्जेक्ट के अन्य (सिंक्रनाइज़) विधियों तक पहुंच सकता हूं, जब किसी को किसी अन्य थ्रेड द्वारा निष्पादित किया जाता है, है ना? – arenaq

+0

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

+0

एक वस्तु के उदाहरण पर विचार करें (मेरी उदाहरण विधि सिंगलटन से है)। इस ऑब्जेक्ट में method1 और method2 है, दोनों सिंक्रनाइज़ हैं। जब इस सिंगलटन क्लास पर एक थ्रेड कॉल विधि 1, कोई अन्य थ्रेड कॉल विधि 2 या कम से कम method3 जो सिंक्रनाइज़ नहीं किया जा सकता है? – arenaq

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