2008-10-23 16 views
29

मैं सी # & का उपयोग कर रहा हूं। 3.5 3.5। OptionA और OptionB के बीच क्या अंतर है?लॉक (लॉकर) और लॉक (variable_which_I_am_using) के बीच अंतर

class MyClass 
{ 
    private object m_Locker = new object(); 
    private Dicionary<string, object> m_Hash = new Dictionary<string, object>(); 

    public void OptionA() 
    { 
     lock(m_Locker){ 
      // Do something with the dictionary 
     } 
    } 

    public void OptionB() 
    { 
     lock(m_Hash){ 
      // Do something with the dictionary 
     } 
    }  
} 

(के बाद से यह एक वेब साइट से जुड़ा हुआ नहीं है, एक मल्टी-थ्रेडेड अनुप्रयोग के लिए एक कैश बनाने, HttpCache वर्ग का उपयोग कर नहीं के लिए मुख्य रूप से) मैं सूत्रण में भिगोना शुरू कर रहा हूँ, और मैं optiona वाक्य रचना को देखने के कई उदाहरणों में मैं ऑनलाइन देखता हूं, लेकिन मुझे समझ में नहीं आता कि क्या, यदि कोई है, तो विकल्प बी पर किया गया कारण।

उत्तर

27

विकल्प बी वस्तु को एक महत्वपूर्ण खंड बनाने के लिए संरक्षित करने के लिए उपयोग करता है। कुछ मामलों में, यह अधिक स्पष्ट रूप से इरादे को संप्रेषित करता है। यदि लगातार इस्तेमाल किया, यह गारंटी देता है की रक्षा की वस्तु के लिए केवल एक महत्वपूर्ण अनुभाग एक समय में सक्रिय हो जाएगा:

lock (m_Hash) 
{ 
    // Across all threads, I can be in one and only one of these two blocks 
    // Do something with the dictionary 
} 
lock (m_Hash) 
{ 
    // Across all threads, I can be in one and only one of these two blocks 
    // Do something with the dictionary 
} 

विकल्प ए कम प्रतिबंधक है। ऑब्जेक्ट को सुरक्षित रखने के लिए यह एक महत्वपूर्ण खंड बनाने के लिए द्वितीयक ऑब्जेक्ट का उपयोग करता है। यदि एकाधिक माध्यमिक वस्तुओं का उपयोग किया जाता है, तो एक समय में संरक्षित ऑब्जेक्ट के लिए सक्रिय एक से अधिक महत्वपूर्ण अनुभाग होना संभव है।

private object m_LockerA = new object(); 
private object m_LockerB = new object(); 

lock (m_LockerA) 
{ 
    // It's possible this block is active in one thread 
    // while the block below is active in another 
    // Do something with the dictionary 
} 
lock (m_LockerB) 
{ 
    // It's possible this block is active in one thread 
    // while the block above is active in another 
    // Do something with the dictionary 
} 

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

3

यह नहीं है कि आप "लॉकिंग" क्या कर रहे हैं, यह लॉक {...} के बीच मौजूद कोड है और यह कि आप निष्पादित होने से रोक रहे हैं।

यदि कोई थ्रेड किसी ऑब्जेक्ट पर लॉक() लेता है, तो यह अन्य थ्रेड को उसी ऑब्जेक्ट पर लॉक प्राप्त करने से रोकता है, और इसलिए दूसरे थ्रेड को ब्रेसिज़ के बीच कोड निष्पादित करने से रोकता है।

इसलिए यही कारण है कि अधिकांश लोग लॉक करने के लिए सिर्फ एक जंक ऑब्जेक्ट बनाते हैं, यह अन्य धागे को उसी जंक ऑब्जेक्ट पर लॉक प्राप्त करने से रोकता है।

+1

मुझे नहीं लगता कि दूसरा और तीसरा अनुच्छेद पहले का पालन कैसे करता है, जो दावा करता है कि आप जो लॉक कर रहे हैं वह महत्वपूर्ण नहीं है। –

1

अच्छा, यह उस चीज़ पर निर्भर करता है जिसे आप लॉक करना चाहते थे (थ्रेडसेफ बनें)।

आम तौर पर मैं केवल थ्रेडसेफ पहुंच को m_Hash तक पहुंच प्रदान करने के लिए OptionB का चयन करूंगा। जहां OptionA के रूप में, मैं लॉकिंग वैल्यू टाइप के लिए उपयोग किया जाता था, जिसका उपयोग लॉक के साथ नहीं किया जा सकता था, या मेरे पास ऑब्जेक्ट्स का एक समूह था जिसे एक साथ लॉक करने की आवश्यकता होती है, लेकिन मैं lock(this)

का उपयोग कर पूरे इंस्टेंस को लॉक करने के लिए नहीं करता
0

आपके द्वारा उपयोग की जा रही वस्तु को लॉक करना बस सुविधा का विषय है। एक बाहरी लॉक ऑब्जेक्ट चीजों को आसान बना सकता है, और यदि साझा संसाधन निजी है, तो संग्रह के साथ (यदि आप ICollection.SyncRoot ऑब्जेक्ट का उपयोग करते हैं) की आवश्यकता होती है।

10

यह समझना महत्वपूर्ण है कि लॉक (m_Hash) हैश का उपयोग करने से अन्य कोड को रोकता है। यह केवल अन्य कोड को चलने से रोकता है जो m_Hash का उपयोग लॉकिंग ऑब्जेक्ट के रूप में भी कर रहा है।

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

विकल्प ए का उपयोग करने का एक और कारण यह है कि यह संभव है कि m_Hash का संदर्भ आपकी कक्षा के बाहर पहुंच योग्य होगा। शायद आपके पास एक सार्वजनिक संपत्ति है जो इसकी पहुंच प्रदान करती है, या हो सकता है कि आप इसे सुरक्षित और व्युत्पन्न कक्षाओं के रूप में घोषित कर सकें। किसी भी मामले में बाहरी कोड के संदर्भ में एक बार, यह संभव है कि बाहरी कोड लॉक के लिए इसका उपयोग करेगा। यह डेडलॉक्स की संभावना भी खुलता है क्योंकि आपके पास नियंत्रण करने का कोई तरीका नहीं है या पता है कि लॉक किस क्रम में लिया जाएगा।

2

मुझे लगता है कि आप "पास" वेरिएबल का दायरा लॉक के दायरे को निर्धारित करेंगे। यानी एक आवृत्ति चर वर्ग के उदाहरण के संबंध में होगा जबकि एक स्थिर चर पूरे AppDomain के लिए होगा।

संग्रह (रिफ्लेक्टर का उपयोग करके) के कार्यान्वयन को देखते हुए, पैटर्न का पालन करना प्रतीत होता है कि सिंक्रूट नामक एक इंस्टेंस वैरिएबल घोषित किया जाता है और संग्रह के उदाहरण के संबंध में सभी लॉकिंग ऑपरेशंस के लिए उपयोग किया जाता है।

7

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

+0

आप वास्तव में प्रश्न का उत्तर नहीं दे रहे हैं, जो 'इस' के अलावा किसी ऑब्जेक्ट का उपयोग करने के 2 तरीकों से संबंधित है। –

+0

मेरा जवाब पर्याप्त स्पष्ट नहीं हो सकता है, मैंने इसे थोड़ा सा संपादित किया है। –

0

OptionA आपके सभी कोड में तब तक जाने का तरीका है, जब आप m_hash तक पहुंचते हैं तो आप इसे लॉक करने के लिए m_Locker का उपयोग करते हैं।

अब इस मामले की कल्पना करें। आप ऑब्जेक्ट को लॉक करते हैं। और आपके द्वारा कॉल किए गए कार्यों में से एक ऑब्जेक्ट में lock(this) कोड सेगमेंट है। इस मामले में यह एक निश्चित अप्राप्य डेडलॉक

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