2011-01-03 18 views
19

मैं सोच रहा हूं कि जावा में वास्तव में "सिंक्रनाइज़" कैसे काम करता है।"सिंक्रनाइज़" वास्तव में क्या करता है? किसी फ़ंक्शन को लॉक करें या ऑब्जेक्ट फ़ंक्शन लॉक करें?

मान लें कि मैं एक बोर्ड-गेम मॉडल करता हूं जिसमें कई फ़ील्ड होते हैं। मैं फ़ील्ड को एक वर्ग (फ़ील्ड) और बोर्ड के रूप में एक वर्ग (बोर्ड) के रूप में कार्यान्वित करता हूं जिसमें कई फ़ील्ड शामिल हैं। चलिए आगे कहते हैं कि मैंने उस क्षेत्र में जाने के लिए एक खिलाड़ी के लिए फ़ील्ड में एक विधि चाल (प्लेयर पीएल) मॉडल किया है। प्रत्येक खिलाड़ी को धागे द्वारा दर्शाया जाता है।

हालांकि सभी थ्रेडों को एक साथ कुछ क्रियाएं करनी चाहिए (उदाहरण के लिए उनके डाइस रोलिंग), केवल एक खिलाड़ी होना चाहिए जो एक समय में चलता है।

मैं यह कैसे सुनिश्चित करूं? क्या विधि को स्थानांतरित करने के लिए पर्याप्त है (प्लेयर पीएल) सिंक्रनाइज़ किया गया है? या मुझे यह सुनिश्चित करने के लिए बोर्ड में एक कैस्केडिंग विधि की आवश्यकता होगी कि एक ही समय में केवल एक खिलाड़ी चलता है? (या क्या कोई बेहतर समाधान है)?

लब्बोलुआब यह करने के लिए इसे लाने के लिए:
"सिंक्रनाइज़" हर वस्तु इस पद्धति है या केवल वस्तु उपयोग में है कि में एक विधि ताला सिंक्रनाइज़ होता है कि में एक विधि ताला चाहेंगे?
और यदि दूसरा मामला है: क्या इस विधि को लागू करने वाले प्रत्येक ऑब्जेक्ट के लिए एक विधि को लॉक करने का कोई आसान तरीका है?

धन्यवाद !!!

class Field { 

    // instance of the board 
    private Board board; 

    public void moveTo(Player p){ 
     synchronized (board) { 
      // move code goes here 
     } 
    } 
} 

यह इतना है कि बोर्ड के अनुसार, केवल एक ही खिलाड़ी एक समय में बढ़ रहा है यह कर देगा:

+5

'सिंक्रनाइज़' कभी भी फ़ंक्शन, अवधि को लॉक नहीं करता है। आप केवल * ऑब्जेक्ट * पर ** ** लॉक कर सकते हैं। एक उदाहरण विधि के साथ, यह 'यह' है। एक स्थिर विधि के साथ, यह कक्षा वस्तु है जिसमें विधि परिभाषित की जाती है (MyClass.class)। –

+0

सिर्फ इसलिए कि आपने पूछा कि मुझे मल्टीथ्रेडिंग की आवश्यकता क्यों है: वास्तव में मैं होमवर्क के रूप में किसी प्रकार का बहुउद्देशीय "पॅकमैन" गेम लागू कर रहा हूं। प्रत्येक खिलाड़ी और हर भूत एक धागा होना चाहिए। हालांकि, मुझे जांचने की ज़रूरत है, अगर कोई खिलाड़ी प्रत्येक चरण के बाद भूत या इसके विपरीत होता है। इस बिंदु पर मुझे कभी-कभी मुझे कुछ बताते हुए अपवाद मिलते हैं जैसे "घोस्ट-ए फील्ड-एक्सवाई से प्लेयर-बी को हटाना चाहता था, लेकिन प्लेयर-बी और नहीं था"। मुझे लगता है कि यह त्रुटि इस तथ्य से आती है कि धागे की चाल सिंक्रनाइज़ नहीं होती थी। – speendo

+0

सिंक्रनाइज़िंग इस समस्या का एक समाधान होगा। लेकिन केवल एक ही नहीं। – Falmarri

उत्तर

27

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

तो आप बस ने लिखा है:

public synchronized void moveTo(Player p){ 

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

+0

yay धन्यवाद! मुझे लगता है कि मैं इसे अब समझता हूं :) – speendo

+1

@ मार्सेल, मदद करने में खुशी हुई। – jjnguy

+0

अंगूठे का बहुत अच्छा नियम: गैर-अंतिम वस्तुओं पर सिंक्रनाइज़/लॉक न करें! – Voo

1

सिंक्रनाइज़ेशन एक संसाधन तक पहुंच लॉक करता है। वह संसाधन या तो एक फ़ंक्शन या ऑब्जेक्ट हो सकता है (this ऑब्जेक्ट सहित)।

हम आपको एक विशिष्ट उदाहरण के बिना विशिष्ट सलाह नहीं दे सकते हैं।

आपके उदाहरण में, यदि खिलाड़ी एक समय में केवल 1 मोड़ ले सकते हैं, तो उन्हें अपने धागे में क्यों होना चाहिए? उन्हें एक ही समय में अपने पासा रोल करने की आवश्यकता क्यों है?

फ़ंक्शन लॉक सिंक्रनाइज़ करना उस विधि के उस उदाहरण के संस्करण को कॉल करता है (जब तक कि यह एक स्थिर विधि न हो)।

And if the second is the case: is there an easy way to lock a function for every object that has this function implemented?

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

6

सिंक्रनाइज़ एक ऑब्जेक्ट लॉक करता है, एक विधि नहीं। जावा में फ़ंक्शन नहीं हैं।

यदि आप सभी ऑब्जेक्ट में केवल एक बार कॉल करने की विधि चाहते हैं तो आप कक्षा जैसे साझा ऑब्जेक्ट को लॉक कर सकते हैं।

मैं सुझाव दूंगा कि आपको केवल सभी धागे/संचालन करने के लिए एक थ्रेड की आवश्यकता होगी और यह कोड को काफी सरल बना देगा। इसे बहु-थ्रेडेड क्यों होना चाहिए?

+1

क्लास ऑब्जेक्ट पर सिंक्रनाइज़ करने से कुछ अनपेक्षित समस्याएं हो सकती हैं यदि स्थिर विधियों को सिंक्रनाइज़ किया गया हो। यदि आप एक विशिष्ट महत्वपूर्ण अनुभाग को सिंक्रनाइज़ करने का प्रयास कर रहे हैं, तो विशेष रूप से इसके लिए लॉक ऑब्जेक्ट पर बनाएं और सिंक्रनाइज़ करें, जैसे 'निजी स्थैतिक अंतिम ऑब्जेक्ट विधिमैटिक्स = नया ऑब्जेक्ट() '। या 6. –

+0

में जोड़े गए समवर्ती प्राइमेटिव का उपयोग करें - बेशक - ऑब्जेक्ट उन्मुख भाषा में किसी फ़ंक्शन को लॉक करने के लिए बेवकूफ होगा ... धन्यवाद, मैंने इससे पहले नहीं सोचा था! – speendo

+2

@ मार्सल: ठीक है। वह निर्भर करता है। पायथन में आप कार्यों को लॉक कर सकते हैं, लेकिन यह वस्तुओं के कार्यों का एक परिणाम है। – Falmarri

1

यह इस बात पर निर्भर करता है कि इसका उपयोग कहां किया जाता है।

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

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

यदि स्पष्ट रूप से निर्दिष्ट वस्तु के साथ उपयोग किया जाता है, तो यह विशेष रूप से स्पष्ट रूप से निर्दिष्ट वस्तु के लॉक ऑब्जेक्ट को पकड़ लेता है। दोबारा, उस समय के दौरान कोई अन्य थ्रेड उस वस्तु के लॉक को विशेष रूप से पकड़ नहीं सकता है।

एक बार जब आप सिंक्रनाइज़ किए गए ब्लॉक का दायरा छोड़ देते हैं, तो आप लॉक पर अपना अनन्य होल्ड छोड़ देते हैं।

+2

महान अवतार, वैसे - क्या यह जीवन के खेल से है? – speendo

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