2012-09-14 21 views
8

मैंने डेडलॉक्स से बचने के लिए सिंक्रूट पैटर्न के बारे में कुछ सामान्य नियम के रूप में कुछ पढ़ा। और कुछ साल पहले एक प्रश्न पढ़ना (यह link देखें), मुझे लगता है कि मैं समझता हूं कि इस पैटर्न के कुछ उपयोग गलत हो सकते हैं। विशेष रूप से, मैं निम्नलिखित वाक्य पर ध्यान केंद्रित this topic से:सिंक्रूट पैटर्न पर कुछ स्पष्टीकरण: इस पैटर्न का उपयोग करने का सही तरीका क्या है?

आप System.Collections में संग्रह के कई पर एक SyncRoot संपत्ति पर ध्यान देंगे। पूर्व-निरीक्षण में, मुझे लगता है कि यह संपत्ति गलती थी ... बाकी आश्वासन दिया है कि हम एक ही गलती नहीं करेंगे क्योंकि हम इन संग्रहों के सामान्य संस्करण बनाते हैं।

वास्तव में, उदाहरण के लिए, List<T> वर्ग SyncRoot संपत्ति को लागू करता है नहीं है, या अधिक सही ढंग से यह स्पष्ट रूप से (this answer देखें) लागू किया गया है, तो आप इसका इस्तेमाल करने में ICollection को कास्ट करना होगा। लेकिन this comment का तर्क है कि एक निजी SyncRoot फ़ील्ड सार्वजनिक बनाना this पर लॉकिंग के रूप में खराब अभ्यास है (this answer देखें), साथ ही this comment में भी पुष्टि की गई है।

तो, यदि मैं सही ढंग से समझता हूं, जब मैं एक गैर थ्रेड-सुरक्षित डेटा संरचना लागू करता हूं, क्योंकि इसे बहु-संदर्भित संदर्भ में उपयोग किया जा सकता है, तो मुझे SyncRoot संपत्ति प्रदान नहीं करना चाहिए (वास्तव में, मुझे नहीं करना चाहिए)। लेकिन मुझे डेवलपर (जो इस डेटा संरचना का उपयोग करेगा) को एक निजी सिंक्रूट ऑब्जेक्ट के साथ निम्नलिखित नमूना कोड में जोड़ने के कार्य के साथ छोड़ देना चाहिए।

public class A 
{ 
    private MyNonThreadSafeDataStructure list; 
    private readonly object list_SyncRoot = new object; 

    public Method1() 
    { 
     lock(list_SyncRoot) 
     { 
      // access to "list" private field 
     } 
    } 

    public Method2() 
    { 
     lock(list_SyncRoot) 
     { 
      // access to "list" private field 
     } 
    } 
} 

सारांश में, मैं समझ गया कि तुल्यकालन/लॉकिंग के लिए सर्वोत्तम प्रथाओं के रूप में निम्नानुसार होना चाहिए:

  1. किसी भी निजी SyncRoot वस्तुओं एक सार्वजनिक संपत्ति के माध्यम से संपर्क में नहीं किया जाना चाहिए, दूसरे शब्दों में, एक कस्टम डेटा संरचना को सार्वजनिक SyncRoot संपत्ति प्रदान नहीं करना चाहिए (this comment भी देखें)।
  2. सामान्य रूप से, लॉकिंग के लिए निजी वस्तुओं का उपयोग करना अनिवार्य नहीं है (this answer देखें)।
  3. यदि किसी वर्ग में संचालन के कई सेट होते हैं जिन्हें सिंक्रनाइज़ करने की आवश्यकता होती है, लेकिन एक दूसरे के साथ नहीं, तो इसमें कई निजी सिंक्रूट ऑब्जेक्ट्स होनी चाहिए (this comment देखें)।

क्या इस पैटर्न के उचित उपयोग से ऊपर लिखा गया है?

+0

मेरी राय यह है कि यदि आप आंतरिक रूप से कक्षा थ्रेड-सुरक्षित बनाना चाहते हैं, तो आप आंतरिक रूप से (निजी रूप से) लॉकिंग करते हैं और दस्तावेज़ करते हैं कि कक्षा आम तौर पर थ्रेड-सुरक्षित है। अन्यथा, _no लॉकिंग_ करें, दस्तावेज़ कि कक्षा थ्रेड-सुरक्षित नहीं है, और अपने वर्ग के उपभोक्ताओं को अपने विशिष्ट उपयोग के लिए अपनी लॉकिंग लागू करने दें। –

उत्तर

4

मैं प्रकार है कि मैं डिजाइन करने के लिए एक SyncRoot संपत्ति जोड़ने से बचें हैं, तो यहां कारण हैं:

  • मेरी प्रकार के उपयोगकर्ता उदाहरण Mutex, या ReaderWriterLock या ReaderWriterLockSlim के लिए अलग तुल्यकालन प्रणाली का उपयोग करने के लिए, आवश्यकता हो सकती है आदि

  • प्रकार फैटर हो जाता है: इसकी ज़िम्मेदारी और बिखरी हुई है। मैं स्पष्ट मल्टीथ्रेडिंग लॉकिंग के लिए समर्थन क्यों जोड़ूं और अन्य फ़्लफ के लिए कोई समर्थन नहीं? मैं केवल एक अभ्यास का पालन करने के लिए उपयोगकर्ता के लिए मजबूर हैं, जो सभी मामलों

  • में सबसे अच्छा समाधान मैं संपत्ति को सही ढंग से लागू करने के लिए की आवश्यकता होगी नहीं हो सकता है (कोई लौटने this या typeof(MyClass)), यानी यह गलत है:

    public object SyncRoot {get {return this;}} 
    

मैं .NET फ्रेमवर्क प्रकारों से SyncRoot संपत्ति का उपयोग करने से भी बचूंगा। अगर मुझे एक प्रकार w/o SyncRoot प्रॉपर्टी थ्रेडसेफ बनाने की ज़रूरत है, तो मैं एक लॉकिंग पैटर्न का उपयोग करूंगा, और यदि किसी प्रकार की संपत्ति है तो मैं अभी भी SyncRoot पर लॉक करने का विकल्प नहीं चुनूंगा। यह मेरी कोड शैली को पढ़ने और बनाए रखने के लिए लगातार और आसान बनाता है।

0

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

एक मनमानी वस्तु को लॉक करने और अपने आंतरिक संग्रह को लॉक करने पर प्रोग्राम की शुद्धता या प्रदर्शन के मामले में बिल्कुल कोई अंतर नहीं है। जब तक दोनों के संदर्भ में परिवर्तन नहीं होता है, तब तक वे मॉनीटर के पैरामीटर के साथ-साथ पैरामीटर भी काम करते हैं। प्रवेश/बाहर निकलें। क्या आपका आंतरिक संग्रह बदल जाएगा? यदि नहीं, तो इसे पढ़ने के रूप में भी चिह्नित करें।

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

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

  • कोई संबंधित समस्या नहीं^_^