2008-10-17 11 views
6

मेरे पास एक कस्टम क्लास है जो ICollection लागू करती है, और यह कक्षा केवल पढ़ने योग्य है, यानी। IsReadOnly सत्य लौटाता है (readonly कीवर्ड का उपयोग करने के विपरीत), और सभी फ़ंक्शंस जो संग्रह में डेटा को सामान्य रूप से संशोधित करते हैं InvalidOperationException के फेंक देते हैं।आईसीओलेक्शन, रीडोनली संग्रह, और सिंक्रनाइज़ेशन। क्या यह सही है?

अब, ICollection (विशेष रूप से ICollection.IsSynchronized और दोस्तों) को लागू करते समय थ्रेड-सुरक्षा समस्याओं पर एक ऐसा निर्माण, और त्वरित स्कीम दिया गया, मैं इस त्वरित और गंदे समाधान के साथ आया।

bool ICollection.IsSynchronised { get{ return true; } } 
object ICollection.SyncRoot { get{ return new Object(); } } 

अब, MSDN में उदाहरण दिया, इस अलग धागे ठीक से लॉक करने के लिए, क्योंकि वे SyncRoot से विभिन्न वस्तुओं हो रही है पैदा नहीं होगी। यह देखते हुए कि यह एक पठनीय संग्रह है, क्या यह एक मुद्दा है? क्या new Object() लौटने के साथ मेमोरी/जीसी मुद्दे हैं? इस कार्यान्वयन के साथ आप देख सकते हैं कि कोई अन्य समस्या?

उत्तर

4

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

मैं जोड़ने की सिफारिश करेंगे:

private readonly object syncRoot = new object(); 
को अपनी कक्षा में

। इसे सिंक्रूट के रूप में वापस करें और आप जाने के लिए अच्छे हैं।

1

मुझे लगता है कि यह मुद्दा होगा यदि क्लाइंट न केवल आपके संग्रह को लॉक करने के लिए आपकी सिंक रूट का उपयोग करते हैं, लेकिन कुछ और। माना जाता है कि उन्होंने संग्रह के आकार को कैश किया - या हो सकता है कि "इस संग्रह का कौन सा सबसेट एक अनुमान से मेल खाता है" - वे उचित रूप से मान लेंगे कि वे आपके संग्रह और उनके अन्य सदस्य दोनों की सुरक्षा के लिए आपके सिंक्रूट का उपयोग कर सकते हैं।

व्यक्तिगत तौर पर मैं शायद ही सब पर SyncRoot उपयोग करें, लेकिन मुझे लगता है कि यह हमेशा एक ही बात वापस जाने के लिए समझदार होगा।

+0

संग्रह प्रभावशाली है, इसे संशोधित करने का कोई तरीका नहीं है (कोर्स के प्रतिबिंब में चारों ओर खुदाई करने के लिए सहेजें), इसलिए इन सभी प्रकार की चीजों की गारंटी दी जानी चाहिए? –

+0

ध्यान दें कि आपके क्लाइंट यह नहीं जानते कि उन्हें एक अपरिवर्तनीय संग्रह मिल रहा है। जाहिर है, वे इसे संशोधित करने की कोशिश नहीं कर रहे हैं (या उन्हें पहले से ही एक त्रुटि मिल जाएगी) लेकिन वे यह सुनिश्चित करने के लिए लॉक हो सकते हैं कि अगर वे एक परिवर्तनीय संग्रह प्रदान किए गए तो वे असफल नहीं होंगे। –

+0

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

2

हर बार एक अलग वस्तु वापस करने के लिए बहुत अजीब लगता है ... असल में, मैं बहुत ही कम (अगर कभी) सिंक्रूट दृष्टिकोण का उपयोग करता हूं, अक्सर मुझे एकाधिक ऑब्जेक्ट्स आदि के बीच सिंक्रनाइज़ करने की आवश्यकता होती है, इसलिए एक अलग वस्तु अधिक अर्थपूर्ण होती है ।

लेकिन अगर डेटा (रीड-ओनली) वास्तव में अपरिवर्तनीय है, क्यों नहीं बस झूठी IsSynchronized से लौटने?

पुन: जीसी - ऐसी कोई वस्तु आमतौर पर कम रहती है और GEN0 में एकत्र की जाती है। यदि आपके पास ऑब्जेक्ट (लॉक के लिए) है, तो यह संग्रह तक ही टिकेगा, लेकिन अधिकतर संभावना किसी भी तरह से चोट नहीं पहुंचीगी ...

यदि आपको लॉक की आवश्यकता है, तो मैं

private readonly object lockObj = new object(); 

तुम भी एक आलसी दृष्टिकोण केवल 'नई' यह जब जरूरत है, जो भावना की एक निश्चित राशि में आता है अगर आप वास्तव में किसी को भी सिंक-लॉक के लिए पूछने के लिए उम्मीद नहीं है (इस्तेमाल कर सकते हैं: सिर्फ एक है IsSynchronized करने के लिए झूठी रिटर्न द्वारा)।

एक और आम तरीका "यह" वापस करना है; यह चीजों को सरल रखता है, लेकिन किसी असंबद्ध उद्देश्य के लिए लॉक के रूप में आपके ऑब्जेक्ट का उपयोग करके किसी अन्य कोड के साथ संघर्ष करता है। दुर्लभ, लेकिन संभव है। यह वास्तव में दृष्टिकोण है कि [MethodImpl] सिंक्रनाइज़ करने के लिए उपयोग करता है।

+1

क्या यह नहीं कह रहा कि ऑब्जेक्ट थ्रेड सुरक्षित नहीं है, वास्तव में, यह है? –

+0

शायद; आईएमओ, सिंक्रनाइज़ किए गए संग्रह के चारों ओर पूरा तर्क थोड़ा सा बोर्क किया जाता है - यह दुर्लभ है कि आप * एकल * ऑपरेशन के लिए थ्रेड-सुरक्षा चाहते हैं - आप आमतौर पर एक मूल्य की जांच करना चाहते हैं और फिर कुछ और करना चाहते हैं। मुझे संदेह है कि सबसे आम कोड इस संपत्ति को कभी भी जांच नहीं पाएगा ... –

+0

मुझे लगता है कि इसका मुख्य कारण फ़ोरैच लूप के चारों ओर लॉक स्टेटमेंट रखना है, इसलिए जब कोई आपके संग्रह को संशोधित करता है तो लूप गड़बड़ नहीं करता है इसके बारे में बताते हुए। –

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