2012-02-07 20 views
43

अंदर मैं अगर यह निर्माण एक त्रुटि का कारण होगा सोच रहा हूँ:ताला ताला

lock(sync) 
{ 
    // something 
    lock(sync) 
    { 
    //something 
    lock(sync) 
    { 
     //something 
    } 
    } 
} 

मैं इस कोड को चलाने की है, और यह ठीक लग रहा है, लेकिन शायद कुछ परिस्थितियों में एक त्रुटि फेंक दिया जा सकता है?

+0

आप ऐसे निर्माण का उपयोग क्यों करना चाहते हैं? – Jehof

+0

क्या आप कुछ ऐसी स्थिति का वर्णन कर सकते हैं जहां आपको ऐसा करने की आवश्यकता होगी? मैं इसे समझने की कोशिश कर रहा हूं, लेकिन ..? –

+0

@ MatíasFidemraizer एक पुनरावर्ती फ़ंक्शन एक ही संसाधन को लॉक कर सकता है। –

उत्तर

38

lock is a wrapper for Monitor.Enter and Monitor.Exit:

The lock keyword calls Enter at the start of the block and Exit at the end of the block. From the former's documentation:

From the documentation for Monitor.Enter:

It is legal for the same thread to invoke Enter more than once without it blocking; however, an equal number of Exit calls must be invoked before other threads waiting on the object will unblock.

क्योंकि Enter और Exit के लिए कॉल जोड़ा जाता है, अपने कोड पैटर्न अच्छी तरह से व्यवहार परिभाषित किया गया है।

A ThreadInterruptedException is thrown if Interrupt interrupts a thread that is waiting to enter a lock statement.

+2

यह ध्यान देने योग्य है कि आंतरिक 'ताला' अनिवार्य रूप से अनावश्यक हैं: आपके पास पहले से ही * लॉक है; इसके लिए फिर से पूछना कभी असफल नहीं होगा। –

+9

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

+0

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

0

MSDN के अनुसार (here और here देखें) इस अच्छी तरह से परिभाषित व्यवहार है और कोई समस्या नहीं का कारण बनता है:

हालांकि, ध्यान दें कि lock एक अपवाद-कम निर्माण होने की गारंटी नहीं है।

12

कारण है कि यह अच्छी तरह से परिभाषित किया गया है व्यवहार की व्याख्या करने के लिए और असफल कभी नहीं होगा:

एक तरफ: This answer has better details about how locks actually work

ताला, Thread स्तर पर होता है तो यह बुला ही धागे पर दूसरी बार निरर्थक हो जाएगा । मुझे लगता है कि इसमें कोई प्रदर्शन जुर्माना नहीं होगा (हालांकि यह इस बात पर निर्भर करेगा कि नेट के आंतरिक वास्तव में कैसे लिखा गया है, इसलिए मैं इसकी गारंटी नहीं दे सकता)

कई बार आपके पास एक सार्वजनिक कार्य होता है जो दूसरे को कॉल करता है आपकी कक्षा में सार्वजनिक कार्य, जिन्हें अलग-अलग उपयोग करते समय लॉक की आवश्यकता होती है। यदि इसकी अनुमति नहीं थी तो निम्नलिखित विफल हो जाएंगे:

private Dictionary<string, int> database = new Dictionary<string, int>(); 
private object databaseLock = new object(); 
public void AddOrUpdate(string item) 
{ 
    lock (databaseLock) 
    { 
     if (Exists(item)) 
      database.Add(item, 1); 
     else 
      ++database[item]; 
    } 
} 
public bool Exists(string item) 
{ 
    lock (databaseLock) 
    { 
     //... Maybe some pre-processing of the key or item... 
     return database.ContainsKey(item); 
    } 
} 
+0

धन्यवाद, मैं यह काम करने की कोशिश कर रहा था कि एक ही ऑब्जेक्ट के लॉक के अंदर लॉक काम करेगा, ठीक है क्योंकि एक विधि दूसरे को कॉल करती है। – mcmillab

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