2010-02-03 19 views
82

मेरी मल्टीथ्रेडेड एएसएमएक्स वेब सेवा में मेरे पास एक वर्ग फ़ील्ड _allData था जो मेरे अपने प्रकार के सिस्टमडाटा था जिसमें List<T> और Dictionary<T>volatile के रूप में चिह्नित हैं। सिस्टम डेटा (_allData) थोड़ी देर में रीफ्रेश किया जाता है और मैं इसे newData नामक एक और ऑब्जेक्ट बनाकर करता हूं और इसे डेटा डेटा संरचनाओं को नए डेटा के साथ भरता हूं। इसके पूर्ण हो जाने मैं सिर्फ आवंटितसंदर्भ असाइनमेंट परमाणु है तो इंटरलाक्ड क्यों है। एक्सचेंज (रेफ ऑब्जेक्ट, ऑब्जेक्ट) की आवश्यकता है?

private static volatile SystemData _allData 

public static bool LoadAllSystemData() 
{ 
    SystemData newData = new SystemData(); 
    /* fill newData with up-to-date data*/ 
    ... 
    _allData = newData. 
} 

इस के बाद से काम परमाणु और धागे पुराने डेटा के संदर्भ में है कि इसका उपयोग जारी रखना और बाकी सिर्फ काम करने के बाद नए सिस्टम डाटा काम करना चाहिए। हालांकि मेरे कॉलेग्यू ने कहा कि volatile कीवर्ड और सरल आकलन का उपयोग करने के बजाय मुझे InterLocked.Exchange का उपयोग करना चाहिए क्योंकि उन्होंने कहा कि कुछ प्लेटफॉर्म पर यह गारंटी नहीं है कि संदर्भ असाइनमेंट परमाणु है। इसके अलावा: जब मैं volatile रूप the _allData क्षेत्र घोषित

Interlocked.Exchange<SystemData>(ref _allData, newData); 

का उत्पादन चेतावनी "एक अस्थिर क्षेत्र के लिए एक संदर्भ के रूप में अस्थिर नहीं माना जाएगा" मैं इस बारे में क्या सोचते चाहिए?

उत्तर

141

यहां कई प्रश्न हैं। उन्हें एक समय में ध्यान में रखते हुए:

संदर्भ असाइनमेंट परमाणु है तो इंटरलाक्ड क्यों है। एक्सचेंज (रेफ ऑब्जेक्ट, ऑब्जेक्ट) की आवश्यकता है?

संदर्भ असाइनमेंट परमाणु है। इंटरलाक्ड। एक्सचेंज केवल संदर्भ असाइनमेंट नहीं करता है। यह एक चर के वर्तमान मूल्य का एक पठन करता है, पुराने मान को दूर करता है, और चरम पर नया मान निर्दिष्ट करता है, सब एक परमाणु ऑपरेशन के रूप में।

मेरे सहयोगी ने कहा कि कुछ प्लेटफार्मों पर यह गारंटी नहीं है कि संदर्भ असाइनमेंट परमाणु है। क्या मेरा सहयोगी सही था?

नहीं। संदर्भ असाइनमेंट सभी .NET प्लेटफ़ॉर्म पर परमाणु होने की गारंटी है।

मेरा सहयोगी झूठी परिसर से तर्क कर रहा है। क्या इसका मतलब है कि उनके निष्कर्ष गलत हैं?

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

चेतावनी उत्पन्न करता है "एक अस्थिर क्षेत्र का संदर्भ अस्थिर नहीं माना जाएगा" मुझे इसके बारे में क्या सोचना चाहिए?

आपको समझना चाहिए कि यह सामान्य रूप से एक समस्या क्यों है। इससे इस बात की समझ हो जाएगी कि चेतावनी इस विशेष मामले में क्यों महत्वहीन है।

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

(मुझे लगता है कि आप पहले से ही सभी को समझते हैं। यदि आपके पास अस्थिरता के अर्थ की विस्तृत समझ नहीं है और यह प्रोसेसर कैश सेमेन्टिक्स को कैसे प्रभावित करता है तो आप समझ नहीं पाते कि यह कैसे काम करता है और अस्थिरता का उपयोग नहीं करना चाहिए। लॉक-फ्री प्रोग्राम सही होने के लिए बहुत मुश्किल हैं; सुनिश्चित करें कि आपका प्रोग्राम सही है क्योंकि आप समझते हैं कि यह कैसे काम करता है, दुर्घटना से सही नहीं।)

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

इसलिए, जब आप ऐसा करते हैं तो संकलक चेतावनी देता है, क्योंकि यह शायद आपके ध्यान से विकसित लॉक-मुक्त तर्क को पूरी तरह से गड़बड़ कर रहा है।

बेशक

, Interlocked.Exchange एक अस्थिर क्षेत्र उम्मीद को पत्र लिखा और सही काम है। चेतावनी इसलिए भ्रामक है। मुझे बहुत खेद है; हमें क्या करना चाहिए था कुछ तंत्र को कार्यान्वित करना जिससे इंटरलॉक.एक्सचेंज जैसी विधि के लेखक ने विधि पर एक विशेषता डाली, "यह विधि जो चरम पर अस्थिर अर्थात् वाष्पशीलता को लागू करती है, इसलिए चेतावनी को दबाएं"।शायद कंपाइलर के भविष्य के संस्करण में हम ऐसा करेंगे।

+4

धन्यवाद! सबसे अच्छा जवाब कभी! –

+0

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

+10

@ माइक: जब कम-लॉक मल्टीथ्रेड परिस्थितियों में संभवतः देखा जाता है, तो मैं अगले व्यक्ति के रूप में अज्ञानी हूं। उत्तर प्रोसेसर से प्रोसेसर में शायद भिन्न होगा। आपको अपने प्रश्न को एक विशेषज्ञ को संबोधित करना चाहिए, या यदि आप रुचि रखते हैं तो विषय पर पढ़ना चाहिए। जो डफी की किताब और उसका ब्लॉग शुरू करने के लिए अच्छी जगहें हैं।मेरा नियम: मल्टीथ्रेडिंग का उपयोग न करें। यदि आपको जरूरी है, तो अपरिवर्तनीय डेटा संरचनाओं का उपयोग करें। यदि आप नहीं कर सकते हैं, ताले का उपयोग करें। केवल तभी जब आपको * ताले के बिना म्यूटेबल डेटा होना चाहिए, तो आपको कम लॉक तकनीक पर विचार करना चाहिए। –

9

या तो आपका कॉलेग्यू गलत है, या वह कुछ जानता है कि सी # भाषा विनिर्देश नहीं है।

5.5 Atomicity of variable references:

"पढ़ता है और निम्नलिखित डेटा प्रकार के लिखते हैं परमाणु कर रहे हैं: bool, चार, बाइट, sbyte, लघु, ushort, uint, पूर्णांक, नाव, और संदर्भ प्रकार के।"

तो, आप दूषित मूल्य प्राप्त करने के जोखिम के बिना अस्थिर संदर्भ को लिख सकते हैं।

आपको निश्चित रूप से सावधान रहना चाहिए कि आप कैसे तय करते हैं कि कौन सा धागा नए डेटा को लेना चाहिए, उस जोखिम को कम करने के लिए जो एक समय में एक से अधिक थ्रेड करता है।

+1

जब तक वे स्मृति सही ढंग से गठबंधन होते हैं तब तक सही है। – zebrabox

+2

@guffa: हाँ मैंने इसे भी पढ़ा है। यह मूल प्रश्न छोड़ देता है "संदर्भ असाइनमेंट परमाणु है तो इंटरलाक्ड क्यों है। एक्सचेंज (रेफ ऑब्जेक्ट, ऑब्जेक्ट) की आवश्यकता है?" अनुत्तरित –

+0

@zebrabox: आपका क्या मतलब है? जब वे नहीं हैं? तुम क्या करोगे? –

6

Interlocked.Exchange< T >

एक निर्धारित मूल्य से करने के लिए निर्दिष्ट प्रकार टी के एक चर सेट और मूल मान देता है, एक परमाणु आपरेशन के रूप में।

यह बदलता है और मूल मूल्य देता है, यह बेकार है क्योंकि आप केवल इसे बदलना चाहते हैं और, जैसे गुफा ने कहा, यह पहले से ही परमाणु है।

जब तक कोई प्रोफाइलर आपके आवेदन में बाधा साबित नहीं होता है, तो आपको असंगत ताले पर विचार करना चाहिए, यह समझना और साबित करना आसान है कि आपका कोड सही है।

2

Iterlocked.Exchange() सिर्फ परमाणु नहीं है, यह भी स्मृति दृश्यता का ख्याल रखता है:

कार्य पर जाना या महत्वपूर्ण वर्गों

छोड़:

निम्नलिखित तुल्यकालन कार्यों स्मृति आदेश सुनिश्चित करने के लिए उचित बाधाओं का उपयोग

सिंक्रनाइज़ेशन ऑब्जेक्ट्स सिग्नल करने वाले कार्य

फ़ंक्शन प्रतीक्षा करें

Interlocked कार्यों

Synchronization and Multiprocessor Issues

इसका मतलब यह है इसके अलावा में यह सुनिश्चित करता है कि Atomicity है कि:

  • धागा के लिए यह बुला:
    • निर्देश का कोई पुनर्व्यवस्था है किया गया (कंपाइलर, रन-टाइम या हार्डवेयर द्वारा)।
  • सभी थ्रेड के लिए:
    • कोई स्मृति कि ऐसा करने से पहले यह निर्देश परिवर्तन इस निर्देश का बना देखेंगे को पढ़ता है।
    • इस निर्देश के बाद सभी पढ़ इस निर्देश द्वारा किए गए परिवर्तन को देखेंगे।
    • यह निर्देश स्मृति के बाद लिखता है जब इस निर्देश परिवर्तन मुख्य स्मृति तक पहुंच गया है (इस निर्देश को फ्लैश करके मुख्य मेमोरी में बदलकर जब यह किया जाता है और हार्डवेयर को इसे समय पर अपने फ्लश करने की अनुमति नहीं देता है)।
संबंधित मुद्दे