2010-07-30 14 views
40

मुझे सिंक्रनाइज़ विधि और सिंक्रनाइज़ ब्लॉक के बीच का अंतर पता है लेकिन मुझे सिंक्रनाइज़ किए गए ब्लॉक भाग के बारे में निश्चित नहीं है।लॉक ऑब्जेक्ट पर सिंक्रनाइज़ किए गए और लॉक के रूप में इसका उपयोग करने के बीच क्या अंतर है?

मान लिया जाये कि मैं इस कोड

class Test { 
    private int x=0; 
    private Object lockObject = new Object(); 

    public void incBlock() { 
    synchronized(lockObject) { 
     x++; 
    } 
    System.out.println("x="+x); 
    } 

    public void incThis() { // same as synchronized method 
    synchronized(this) { 
     x++; 
    } 
    System.out.println("x="+x); 
    } 
} 

है इस मामले में क्या का उपयोग कर lockObject और इस ताला के रूप में प्रयोग के बीच का अंतर है? यह मेरे जैसा ही लगता है ..

जब आप सिंक्रनाइज़ ब्लॉक का उपयोग करने का निर्णय लेते हैं, तो आप कैसे तय करते हैं कि कौन सा ऑब्जेक्ट लॉक होना है?

+5

मैं http://stackoverflow.com/questions/3047564/java-synchronized-method-lock-on-object-or-method आप जवाब को देखें, तो में अपने प्रश्न का उत्तर मिल गया है, यह है बहुत स्पष्ट है कि अगर 2 धागे (टी 1 और टी 2) हैं जहां टी 1 x.addA() और टी 2 कॉल x.addB() कहते हैं। यदि दोनों addA और addB इसे लॉक के रूप में उपयोग करते हैं, तो x.addA() और x.addB() समवर्ती रूप से नहीं चल सकते हैं। जबकि यदि अगर Adda और addB ताला के लिए अलग वस्तु का उपयोग करता है, दोनों विधि बस कुछ जांच करने के लिए समवर्ती – GantengX

+2

चला सकते हैं: उपरोक्त उदाहरण में, जब आप प्रभावी रूप से एक्स के लिए उपयोग की रक्षा करने के lockObject का उपयोग वहाँ एक स्थिति है जहाँ एक और धागा सकता है नहीं है सिंक्रनाइज़ किए गए ब्लॉक के बाद प्राप्त करें लेकिन println से पहले और x को फिर से बढ़ाएं? अर्थात। क्या आपको वास्तव में सिंक्रनाइज़ ब्लॉक के भीतर println की आवश्यकता है? –

+1

आह सच है, मैं सिंक्रनाइज़ ब्लॉक में डाला है चाहिए, लेकिन मैं पहले से ही मेरे अपने प्रश्न का उत्तर दिया: डी – GantengX

उत्तर

54

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

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

+0

क्या आप और विस्तार कर सकते हैं? क्लास 'ए' कक्षा 'बी' के उदाहरण के साथ कहें। अब 'बी' में कुछ सदस्य चर हैं। जब 'ए' 'बी' की कोई विधि कहता है, तो यह इस/इंस्टेंस सदस्य पर लॉक हो जाता है ... सही? मतलब 'बी' के उदाहरण या उसके सदस्य के उदाहरण पर ताला हो जाता है ... क्या आप सिर्फ अंतर को समझा सकते हैं? – Parth

+1

@ पार्थ: आपकी टिप्पणी स्पष्ट नहीं है - क्या आपका मतलब है * प्रत्येक विधि के लिए निजी लॉक पर * बी * लॉक होना चाहिए? यह कक्षा के उद्देश्य पर निर्भर करता है। अधिकांश वर्गों को ईमानदार होने के लिए थ्रेड-सुरक्षित होने की कोशिश करने की आवश्यकता नहीं है। –

+0

याह, इसलिए मुझे सिंक विधि बनाने की जरूरत है, यह 'इस' के बजाय निजी सदस्य ऑब्जेक्ट का उपयोग करें ... सही? ठीक है ... – Parth

0

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

+0

मैं समझता हूं कि यह उचित सिंक्रनाइज़ेशन नहीं है क्योंकि यह अलग-अलग विधि के लिए अलग-अलग लॉक का उपयोग करता है, मैं लॉक – GantengX

+0

ओह के लिए 'इस' और 'लॉकऑब्जेक्ट' का उपयोग करने के बीच अंतर को समझने की कोशिश कर रहा हूं .. आपके प्रश्न को गलतफहमी के लिए खेद है। तो इसके लिए, जवाब जॉन स्कीट ने जो जवाब दिया है वैसा ही होगा। – Gopi

4

Effective Java Second Edition की 67 67 अत्यधिक सिंक्रनाइज़ेशन से बचें, इस प्रकार मैं एक निजी लॉक ऑब्जेक्ट पर सिंक्रनाइज़ कर दूंगा।

+0

यह प्रश्न (प्रयोग 'synchronized' या' Locks'), कोई वास्तविक विवरण, टूटा हुआ लिंक (उत्तर नहीं मिलता है [संग्रहीत संस्करण] (http://web.archive.org/web/20090904194857/http://java। sun.com/docs/books/effective/index.html))। Downvoted। –

1

जावा में प्रत्येक ऑब्जेक्ट मॉनीटर के रूप में कार्य कर सकता है। एक का चयन करना आप जो ग्रैन्युलरिटी चाहते हैं उस पर निर्भर है। 'इस' का चयन करने का लाभ और नुकसान है कि अन्य वर्ग एक ही मॉनीटर पर सिंक्रनाइज़ भी कर सकते हैं। हालांकि मेरी सलाह सीधे सिंक्रनाइज़ कीवर्ड का उपयोग करने से बचने के लिए है और इसके बजाय java.util.concurrency लाइब्रेरी से संरचनाओं का उपयोग करें जो उच्च स्तर हैं और अच्छी तरह परिभाषित अर्थशास्त्र हैं। यह पुस्तक एक बहुत उल्लेखनीय विशेषज्ञों से उस में महान सलाह के बहुत है: http://amzn.com/0321349601

9

मैं इस एक ही सवाल है जब मैं अभ्यास में जावा संगामिति पढ़ रहा था था अभ्यास में

जावा संगामिति, और मैंने सोचा कि मैं जोड़ना होगा जॉन स्कीट और स्पुलारा द्वारा दिए गए उत्तरों पर कुछ जोड़ा परिप्रेक्ष्य।

यहां कुछ उदाहरण कोड है जो doStuff(ValueHolder) विधि निष्पादित करते समय भी "त्वरित" setValue(int)/getValue() विधियों को अवरुद्ध करेगा।

public class ValueHolder { 
    private int value = 0; 

    public synchronized void setValue(int v) { 
     // Or could use a sychronized(this) block... 
     this.value = 0; 
    } 

    public synchronized int getValue() { 
     return this.value; 
    } 
} 

public class MaliciousClass { 

    public void doStuff(ValueHolder holder) { 
     synchronized(holder) { 
      // Do something "expensive" so setter/getter calls are blocked 
     } 
    } 
} 

तुल्यकालन के लिए this का उपयोग करने का नकारात्मक पक्ष यह अन्य वर्गों (this के माध्यम से नहीं, निश्चित रूप से) अपने वर्ग के लिए एक संदर्भ पर सिंक्रनाइज़ कर सकते हैं है।synchronized कीवर्ड की दुर्भावनापूर्ण या अनजाने में उपयोग करते हुए अपना वस्तु के संदर्भ पर ताला लगा अपनी कक्षा समवर्ती उपयोग के तहत खराब व्यवहार करने के लिए, के रूप में एक बाहरी वर्ग प्रभावी रूप से अपने this -synchronized तरीकों ब्लॉक कर सकते हैं पैदा कर सकता है और कुछ भी नहीं करने के लिए आप कर सकते हैं (अपनी कक्षा में) नहीं है रनटाइम पर इसे प्रतिबंधित करें। इस संभावित pitfall से बचने के लिए, आप private final Object पर सिंक्रनाइज़ करेंगे या java.util.concurrent.locks में Lock इंटरफ़ेस का उपयोग करें।

इस सरल उदाहरण के लिए, आप बारी-बारी से एक AtomicInteger बल्कि सेटर/गेटर सिंक्रनाइज़ करने से इस्तेमाल कर सकते हैं।

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

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