2009-10-17 8 views
18

मैं Volatile reads and writes, and timeliness के बारे में जो डफी पोस्ट पढ़ रहा हूँ, और मैं पोस्ट में पिछले कोड नमूने के बारे में कुछ समझने की कोशिश कर रहा हूँ:Interlocked.CompareExchange एक स्मृति बाधा का उपयोग करता है?

while (Interlocked.CompareExchange(ref m_state, 1, 0) != 0) ; 
m_state = 0; 
while (Interlocked.CompareExchange(ref m_state, 1, 0) != 0) ; 
m_state = 0; 
… 

जब दूसरे CMPXCHG आपरेशन निष्पादित किया जाता है, यह एक स्मृति बाधा का उपयोग करता है यह सुनिश्चित करने के लिए कि का मूल्य m_state वास्तव में इसके लिए लिखा गया नवीनतम मूल्य है? या यह केवल कुछ मान का उपयोग करेगा जो प्रोसेसर के कैश में पहले से संग्रहीत है? (मानते हैं कि m_state को अस्थिर घोषित नहीं किया गया है)।
यदि मैं सही ढंग से समझता हूं, यदि सीएमपीएक्सएचजी मेमोरी बाधा का उपयोग नहीं करेगा, तो पूरी ताला अधिग्रहण प्रक्रिया उचित नहीं होगी क्योंकि यह बहुत अधिक संभावना है कि लॉक प्राप्त करने वाला पहला धागा, वह होगा जो निम्नलिखित सभी ताले प्राप्त करें। क्या मैं सही ढंग से समझता हूं, या क्या मैं यहां कुछ खो रहा हूं?

संपादित करें: मुख्य प्रश्न यह है कि वास्तव में तुलना एक्सचेंज को कॉल करना m_state के मान को पढ़ने का प्रयास करने से पहले स्मृति बाधा उत्पन्न करेगा। तो जब वे 0 को असाइन करना चाहते हैं तो वे सभी को थ्रेड के लिए दिखाई देंगे जब वे तुलना एक्सचेंज को फिर से कॉल करने का प्रयास करते हैं।

उत्तर

22

कोई भी x86 निर्देश जिसमें लॉक उपसर्ग में पूर्ण मेमोरी बाधा है। जैसा कि हाबिल का जवाब दिखाया गया है, इंटरलाक्ड * एपीआई और तुलना एक्सचेंज लॉक- lock cmpxchg जैसे पूर्ववर्ती निर्देश का उपयोग करें। तो, यह स्मृति बाड़ का तात्पर्य है।

हां, इंटरलाक्ड। कॉम्पारे एक्सचेंज मेमोरी बाधा का उपयोग करता है।

क्यों? क्योंकि x86 प्रोसेसर ने ऐसा किया था। इंटेल की Volume 3A: System Programming Guide Part 1, धारा 7.1.2.2 से:

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

volatile इस चर्चा के साथ कुछ लेना देना नहीं है। यह परमाणु संचालन के बारे में है; सीपीयू में परमाणु संचालन का समर्थन करने के लिए, x86 सभी पिछले लोड और स्टोर को पूरा करने की गारंटी देता है।

+0

उल्लेख करने के लायक है कि यह पूर्ण FENCE प्रदान करता है और आधे बाड़ नहीं। –

10

ref विशेष रूप से की तरह बातों में हमेशा की तरह volatile नियमों का पालन नहीं करता है,:

volatile bool myField; 
... 
RunMethod(ref myField); 
... 
void RunMethod(ref bool isDone) { 
    while(!isDone) {} // silly example 
} 

यहाँ, RunMethodisDone के लिए बाहरी परिवर्तन को पहचानना इसकी गारंटी नहीं है यहां तक ​​कि अंतर्निहित क्षेत्र (myField) volatile है, हालांकि; RunMethod इसके बारे में नहीं पता है, इसलिए सही कोड नहीं है।

हालांकि! यह एक गैर मुद्दा होना चाहिए:

  • अगर आप Interlocked उपयोग कर रहे हैं, तो के लिए Interlocked का उपयोग क्षेत्र
  • करने के लिए सभी पहुँच यदि आप lock उपयोग कर रहे हैं, तो करने के लिए सभी पहुँच के लिए lock का उपयोग फ़ील्ड

उन नियमों का पालन करें और इसे ठीक काम करना चाहिए।


संपादन पुन: संपादित करें; हां, व्यवहारInterlocked का एक महत्वपूर्ण हिस्सा है। ईमानदार होने के लिए, मुझे नहीं पता कि यह कैसे कार्यान्वित किया जाता है (मेमोरी बाधा, आदि - ध्यान दें कि वे "InternalCall" विधियां हैं, इसलिए मैं जांच नहीं कर सकता; -पी) - लेकिन हाँ: एक थ्रेड से अपडेट तुरंत दिखाई देंगे अन्य सभी तक वे Interlocked विधियों (इसलिए ऊपर मेरा बिंदु) का उपयोग करते हैं।

+0

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

+0

@Marc: InternalCall विधियों का स्रोत देखा जा सकता है (अधिकांश भाग के लिए) साझा स्रोत सीएलआई एसएससीएलआई, उर्फ ​​रोटर। Interlocked.CompareExchange इस दिलचस्प पढ़ने में समझाया गया है: http://www.moserware.com/2008/09/how-do-locks-lock.html – Abel

2

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

चूंकि आप सी # फ़ंक्शन का संदर्भ पारित कर रहे हैं, अंतर्निहित असेंबलर कोड वास्तविक पूर्णांक के पते के साथ काम करेगा, इसलिए परिवर्तनीय पहुंच को अनुकूलित नहीं किया जाएगा। यह बिल्कुल अपेक्षित काम करेगा।

संपादित करें: यह लिंक है जिसे एएसएम अनुदेश बेहतर के व्यवहार बताते है: http://faydoc.tripod.com/cpu/cmpxchg.htm
आप देख सकते हैं, बस एक लिखने चक्र के लिए मजबूर कर के कारण रुक गया है, ताकि किसी भी अन्य "सूत्र" (पढ़ें: अन्य सीपीयू कोर) जो कि एक ही समय में बस का उपयोग करने की कोशिश करेगा, एक प्रतीक्षा कतार में रखा जाएगा।

+0

दरअसल, विपरीत (आंशिक रूप से) सत्य है। इंटरलाक्ड एक परमाणु संचालन करता है और 'cmpxchg' असेंबली निर्देश का उपयोग करता है। इसे अन्य धागे को प्रतीक्षा राज्य में रखने की आवश्यकता नहीं है, इसलिए यह बहुत ही प्रभावशाली है। इस पृष्ठ पर "आंतरिक कॉल के अंदर" अनुभाग देखें: http://www.moserware.com/2008/09/how-do-locks-lock.html – Abel

2

MSDN Win32 एपीआई कार्यों के बारे में कहते हैं: "इंटरलॉक कार्यों में से अधिकांश सभी Windows प्लेटफार्मों पर पूर्ण स्मृति बाधाओं प्रदान"

(अपवाद स्पष्ट मोल/रिलीज अर्थ विज्ञान के साथ काम करता है Interlocked कर रहे हैं)

उस से मैं निष्कर्ष निकालूंगा कि सी # रनटाइम इंटरलाक्ड एक ही गारंटी देता है, क्योंकि उन्हें अन्यथा समान व्यवहार के साथ दस्तावेज किया जाता है (और वे प्लेटफ़ॉर्म पर आंतरिक CPU विवरणों को हल करते हैं)। दुर्भाग्यवश, एमएसडीएन की प्रलेखन के बजाय नमूने डालने की प्रवृत्ति के साथ, यह स्पष्ट रूप से वर्तनी नहीं है।

6

उसी नाम से Win32 API फ़ंक्शंस के साथ कुछ तुलना की प्रतीत होती है, लेकिन यह थ्रेड सी # Interlocked कक्षा के बारे में है। अपने विवरण से, यह गारंटी है कि इसके संचालन परमाणु हैं। मुझे यकीन नहीं है कि यह कैसे "पूर्ण स्मृति बाधाओं" का अनुवाद करता है जैसा कि यहां अन्य उत्तरों में उल्लिखित है, लेकिन स्वयं के लिए जज।

uniprocessor सिस्टम पर, कुछ भी नहीं विशेष होता है, वहाँ सिर्फ एक अनुदेश है:

FASTCALL_FUNC CompareExchangeUP,12 
     _ASSERT_ALIGNED_4_X86 ecx 
     mov  eax, [esp+4] ; Comparand 
     cmpxchg [ecx], edx 
     retn 4    ; result in EAX 
FASTCALL_ENDFUNC CompareExchangeUP 

लेकिन मल्टीप्रोसेसर सिस्टम पर, एक हार्डवेयर ताला एक ही समय में डेटा का उपयोग करने के लिए अन्य कोर को रोकने के लिए प्रयोग किया जाता है:

FASTCALL_FUNC CompareExchangeMP,12 
     _ASSERT_ALIGNED_4_X86 ecx 
     mov  eax, [esp+4] ; Comparand 
    lock cmpxchg [ecx], edx 
     retn 4    ; result in EAX 
FASTCALL_ENDFUNC CompareExchangeMP 

यहां और कुछ गलत निष्कर्षों के साथ एक दिलचस्प पढ़ा गया है, लेकिन इस विषय पर सभी उत्कृष्ट उत्कृष्ट यह blog post on CompareExchange है।

0

ईसीएमए -335 (धारा I.12.6 के अनुसार)।5):

5. स्पष्ट परमाणु संचालन। कक्षा पुस्तकालय सिस्टम में विभिन्न परमाणु संचालन प्रदान करता है। थ्रेडिंग। इंटरटरॉक कक्षा। ये ऑपरेशंस (उदा।, वृद्धि, विघटन, एक्सचेंज, और तुलना एक्सचेंज) निहित अधिग्रहण/रिलीज संचालन निष्पादित करें।

तो, इन आपरेशनों कम से कम विस्मय की सिद्धांत का पालन करें।

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