2008-11-02 18 views
5

सी ++ में एक आम पैटर्न एक वर्ग बनाने के लिए है जो लॉक लपेटता है - ऑब्जेक्ट बनने पर लॉक या तो स्पष्ट रूप से लिया जाता है, या बाद में स्पष्ट रूप से लिया जाता है। जब वस्तु दायरे से बाहर हो जाती है, तो डीटीओ स्वचालित रूप से लॉक जारी करता है। क्या यह सी # में ऐसा करना संभव है? जहां तक ​​मैं समझता हूं कि इस बात की कोई गारंटी नहीं है कि ऑब्जेक्ट के दायरे से बाहर होने के बाद सी # में डॉटोर दौड़ जाएगा।क्या सी # में स्कोप्ड लॉक को कार्यान्वित करना संभव है?

स्पष्टीकरण: सामान्य में कोई लॉक, स्पिनलॉक, रीडरवाइटर लॉक, जो भी हो। कॉलिंग स्वयं को पैटर्न के उद्देश्य को हराता है - जैसे ही हम बाहर निकलते हैं, लॉक जारी होने के लिए - कोई फर्क नहीं पड़ता कि हम बीच में वापसी कहलाते हैं, अपवाद या क्या नहीं फेंक देते हैं। इसके अलावा, जहां तक ​​मैं समझता हूं कि जीसी के लिए केवल कतार वस्तु है, इसे तुरंत नष्ट नहीं किया जाएगा ...

उत्तर

5

using के बारे में आपकी समझ गलत है, यह निर्धारित करने के लिए एक निर्धारित तरीका है कि जीसी के लिए कोई कतार नहीं है)।

सी # lock कीवर्ड प्रदान करता है जो एक विशेष लॉक प्रदान करता है और यदि आप अलग-अलग प्रकार (उदा। पढ़ने/लिखना) चाहते हैं तो आपको using कथन का उपयोग करना होगा।

पीएस This thread आपकी रूचि रख सकता है।

4

यह सच है कि आपको पता नहीं है कि डॉटोर कब चल रहा है ... लेकिन, अगर आप IDISposable इंटरफ़ेस को कार्यान्वित करते हैं, और उसके बाद या तो 'उपयोग' ब्लॉक का उपयोग करते हैं या 'डिसपोज़()' को कॉल करते हैं, तो आपके पास अपना कोड डालने की जगह होगी।

प्रश्न: जब आप "लॉक" कहते हैं, तो क्या आपका मतलब थ्रेड लॉक है ताकि एक समय में केवल एक थ्रेड ऑब्जेक्ट का उपयोग कर सके? जैसा कि:

lock (_myLockKey) { ... } 

कृपया स्पष्ट करें।

12

तीमुथियुस के उत्तर को बढ़ाने के लिए, लॉक स्टेटमेंट मॉनीटर का उपयोग करके एक स्कोप्ड लॉक बनाता है। मूलतः, यह कुछ इस तरह में तब्दील हो:

lock(_lockKey) 
{ 
    // Code under lock 
} 

// is equivalent to this 
Monitor.Enter(_lockKey) 
try 
{ 
    // Code under lock 
} 
finally 
{ 
    Monitor.Exit(_lockKey) 
} 

सी # में आप शायद ही कभी पैटर्न के इस प्रकार के लिए dtor का उपयोग (देखें का उपयोग कर बयान/IDisposable)। कोड में एक चीज जो आप नोटिस कर सकते हैं वह यह है कि यदि मॉनिटर के बीच एक एसिंक अपवाद होता है। एंटर करें और कोशिश करें, ऐसा लगता है कि मॉनिटर जारी नहीं किया जाएगा। जेआईटी वास्तव में एक विशेष गारंटी देता है कि यदि एक मॉनीटर। एन्विन अपवाद को तुरंत अवरुद्ध करने से पहले एन्टर अपवाद तब तक नहीं होगा जब तक कि रिलीज को सुनिश्चित करने के लिए ब्लॉक को अवरुद्ध न करें।

3

पूर्णता के लिए using और IDisposable का उपयोग किए बिना समान RAII प्रभाव प्राप्त करने का एक और तरीका है। सी # using आमतौर पर कुछ और विचारों के लिए स्पष्ट (see also here) है, लेकिन अन्य भाषाओं में (जैसे जावा), या यहां तक ​​कि सी # में using किसी कारण से उचित नहीं है, यह जानना उपयोगी है।

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

उदा।:


funkyObj.InOut(delegate{ System.Console.WriteLine("middle bit"); }); 

क्या InOut विधि करता है के आधार पर, उत्पादन हो सकता है कुछ की तरह:

 
first bit 
middle bit 
last bit 

मैं कहता हूँ के रूप में, इस सवाल का जवाब पूर्णता के लिए ही है, IDisposable साथ using के पिछले सुझाव, के रूप में lock कीवर्ड के साथ-साथ 99% समय बेहतर होगा।

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

0

मुझे इस तथ्य से वास्तव में परेशान किया गया है कि using डेवलपर को ऐसा करने के लिए याद है - सबसे अच्छा आपको एक चेतावनी मिलती है, जो ज्यादातर लोग कभी भी किसी त्रुटि को बढ़ावा देने के लिए परेशान नहीं होते हैं। तो, मैं इस तरह के विचार से टकरा रहा हूं - यह क्लाइंट को कम से कम चीजों को सही तरीके से करने की कोशिश करता है। सौभाग्य से और दुर्भाग्यवश, यह एक बंद है, इसलिए ग्राहक अभी भी संसाधन की प्रतिलिपि रख सकता है, और बाद में इसका उपयोग करने का प्रयास कर सकता है - लेकिन यह कोड कम से कम ग्राहक को सही दिशा में धक्का देने की कोशिश करता है ...

public class MyLockedResource : IDisposable 
{ 
    private MyLockedResource() 
    { 
     Console.WriteLine("initialize"); 
    } 

    public void Dispose() 
    { 
     Console.WriteLine("dispose"); 
    } 

    public delegate void RAII(MyLockedResource resource); 

    static public void Use(RAII raii) 
    { 
     using (MyLockedResource resource = new MyLockedResource()) 
     { 
      raii(resource); 
     } 
    } 

    public void test() 
    { 
     Console.WriteLine("test"); 
    } 
} 

अच्छा उपयोग:

MyLockedResource.Use(delegate(MyLockedResource resource) 
{ 
    resource.test(); 
}); 

बुरा उपयोग! (दुर्भाग्य से, इसे रोका नहीं जा सकता ...)

MyLockedResource res = null; 
MyLockedResource.Use(delegate(MyLockedResource resource) 
{ 
    resource.test(); 
    res = resource; 
    res.test(); 
}); 
res.test(); 
संबंधित मुद्दे