2009-07-05 11 views
18

Win32 एपीआई में इंटरलॉक्ड XXX कार्यों का एक सेट है जो परमाणु रूप से और सिंक्रनाइज़ रूप से सरल चर का उपयोग करता है, हालांकि वैरिएबल के मान को पुनः प्राप्त करने के लिए कोई इंटरलॉक रीड फ़ंक्शन नहीं लगता है। कैसे?InterlockedRead कहां है?

MSDN says कि:

सरल रीड और राईट ठीक से गठबंधन करने के लिए 32-बिट चर परमाणु संचालन

हैं, लेकिन कहते हैं:

हालांकि, उपयोग करने के लिए गारंटी नहीं है सिंक्रनाइज़ किया जाना चाहिए। हालांकि, सिंक्रनाइज़ होने की पहुंच की गारंटी नहीं है। यदि दो धागे एक ही चर से पढ़ रहे हैं और लिख रहे हैं, तो आप यह निर्धारित नहीं कर सकते कि एक धागा इसके पढ़ने के संचालन को करने से पहले अपने पढ़ने के संचालन को करेगा या नहीं।

जिसका अर्थ है, जैसा कि मैं समझता हूं, एक चर का एक सरल पठन ऑपरेशन हो सकता है जबकि दूसरा, कहें, इंटरलॉकएड ऑपरेशन जगह पर है। तो एक चर पढ़ने के लिए एक interlocked समारोह क्यों नहीं है?

मुझे लगता है कि मान इंटरलॉक किए गए परिणाम के रूप में पढ़ा जा सकता है शून्य, लेकिन यह जाने का सही तरीका प्रतीत नहीं होता है।

उत्तर

7

इसे लागू करने का सामान्य तरीका तुलना-विनिमय संचालन (उदा। InterlockedCompareExchange64) का उपयोग करना है, जहां दोनों मान समान हैं। मुझे एक झुकाव संदेह है कि इसे किसी कारण से 0 के जोड़ से अधिक कुशलता से किया जा सकता है, लेकिन मेरे पास इसका समर्थन करने के लिए कोई सबूत नहीं है।

दिलचस्प बात यह है कि .NET 2.Interlocked कक्षा को .NET 2.0 तक Read विधि प्राप्त नहीं हुई थी। मुझे विश्वास है कि Interlocked.ReadInterlocked.CompareExchange का उपयोग कर कार्यान्वित किया गया है। (ध्यान दें कि Interlocked.Read के लिए प्रलेखन मुझे कुछ हद तक भ्रामक बनाता है - यह परमाणुता के बारे में बात करता है, लेकिन अस्थिरता नहीं, जिसका अर्थ है .NET पर कुछ विशिष्ट है। मुझे यकीन नहीं है कि Win32 मेमोरी मॉडल नए लिखित मूल्यों की दृश्यता के बारे में गारंटी देता है अलग धागा, यदि कुछ भी हो।)

+0

अस्थिरता के लिए आपके पास थ्रेड है। वोल्टाइल रीड परिवार। –

+0

@ जेएस: क्या एक विशिष्ट कारण है जिसे आपने InterlockedCompareExchange64 (64 पर जोर देने के साथ) की सलाह दी है? Interlocked.Read भी 64 बिट मानों के साथ काम करता है, और कहता है कि "रीड विधि 64-बिट सिस्टम पर अनावश्यक है", जो कुछ हद तक इंगित करता है कि 32 बिट मशीन पर 32 बिट मानों को पढ़ने के दौरान इंटरलाक्ड कॉम्पैयरएक्सनेज (32 बिट संस्करण) आवश्यक नहीं है। –

+0

@Remus: Thread.VolatileRead के बारे में अच्छा बिंदु, हालांकि प्रलेखन का तात्पर्य है कि आपको * बिल्कुल * चिंता करने की आवश्यकता नहीं है (थ्रेड को इंगित करने के बजाय। वोल्टाइल रीड, जो अधिक समझ में आएगा)। @ कारण: 64 बिट संस्करण चुनने के लिए कोई विशेष कारण नहीं, नहीं। मुझे लगता है कि यहां पर्याप्त सूक्ष्मता है कि मैं यह दावा नहीं करना चाहूंगा कि इसमें से कोई भी किए बिना दूर जाने की कोशिश करने के मामले में क्या आवश्यक है। –

7

मुझे लगता है कि "सिंक्रनाइज़ नहीं" की आपकी व्याख्या गलत है। सरल परमाणु पढ़ता है, लेकिन आपको खुद को पुन: समन्वय और स्मृति दृश्यता के मुद्दों का ख्याल रखना होगा। पूर्व को उचित स्थानों पर बाड़ निर्देशों का उपयोग करके संभाला जाता है, उत्तरार्द्ध पढ़ने के साथ एक गैर-मुद्दा है (लेकिन संभावित समवर्ती लेखन को उचित दृश्यता सुनिश्चित करना है, जो इंटरलॉक फ़ंक्शन पर वे LOCKED ASM निर्देशों को मानचित्रित करते हैं) ।

+0

मेरी चिंताओं को सुनने में खुशी हुई पूरी तरह से बेवकूफ नहीं थी :) –

+0

@zvrba: मुझे लगता है कि जो मैं सिंक्रनाइज़ करता हूं (वास्तव में, जो एमएसडीएन सिंक्रनाइज़ करता है) वह है जिसे आप फिर से कॉल करते हैं। वैसे भी, मैं वास्तव में नहीं देखता कि नीचे की रेखा क्या है। क्या यह एक उत्तर या टिप्पणी है? –

+1

यह एक उत्तर है - इंटरलाक्ड रीड (जो भी हो सकता है) आवश्यक नहीं है। – zvrba

2

इस पूरे चर्चा की जड़ उचित संरेखण, जो विभाजन xxx की मैं में devined है, भाग में '12.6.2 Alignment' है:

Built-in datatypes shall be properly aligned, which is defined as follows: 
• 1-byte, 2-byte, and 4-byte data is properly aligned when it is stored at 
    a 1-byte, 2-byte, or 4-byte boundary, respectively. 
• 8-byte data is properly aligned when it is stored on the same boundary 
    required by the underlying hardware for atomic access to a native int. 

मूल रूप से, सभी 32-बिट मान आवश्यक संरेखण है, और पर एक 64-बिट प्लेटफ़ॉर्म, 64-बिट मानों के लिए आवश्यक संरेखण भी होता है।

नोट: स्मृति में कक्षाओं के लेआउट को स्पष्ट रूप से बदलने के लिए विशेषताएं हैं, जो आपको इस संरेखण को खोने का कारण बन सकती हैं। ये विशेष रूप से इस उद्देश्य के लिए विशेषताएँ हैं, इसलिए जब तक कि आप लेआउट को बदलने के लिए सेट नहीं करते हैं, यह आपके लिए लागू नहीं होना चाहिए।

इस तरह से, Interlocked वर्ग का उद्देश्य संचालन प्रदान करना है (पैराफ्रेश के लिए) केवल उनके 'पहले' या 'बाद' राज्य में देखा जा सकता है। इंटरलाक्ड ऑपरेशंस आमतौर पर स्मृति को संशोधित करते समय चिंता का विषय होता है (आमतौर पर कुछ गैर-तुच्छ तुलना-विनिमय प्रकार के तरीके में)। चूंकि आपको मिली एमएसडीएन लेख इंगित करता है, पढ़े जाने वाले ऑपरेशन (जब सही तरीके से गठबंधन किया जाता है) को बिना किसी सावधानी के हर समय परमाणु माना जा सकता है।

जब पढ़ने के संचालन के साथ काम कर रहे है लेकिन अन्य कारणों हैं:

  • आधुनिक CPUs पर, हालांकि पढ़ने परमाणु हो सकता है, यह भी कहीं न कहीं एक बासी कैश से गलत मान वापस आ सकते हैं ... इस जहां है आप क्षेत्र 'अस्थिर' व्यवहार जैसा कि आप उम्मीद
  • आप 32-बिट हार्डवेयर पर एक 64-बिट मूल्य के साथ काम कर रहे हैं, तो प्राप्त करने के लिए बनाने के लिए आवश्यकता हो सकती है, आप पूरे 64 की गारंटी करने के Interlocked.Read आपरेशन उपयोग करना पड़ सकता -बिट मान एक परमाणु ऑपरेशन में पढ़ा जाता है (अन्यथा इसे 2 अलग-अलग 32-बिट रीड के रूप में किया जा सकता है जो कि हो सकता है एम स्मृति अद्यतन के दोनों तरफ)
  • आपके पढ़ने/लिखने के पुन: क्रम में आपको अपेक्षित मूल्य प्राप्त नहीं हो सकता है; जो मामले में कुछ स्मृति बाधा जरूरत हो सकती है (या तो स्पष्ट है, या Interlocked वर्ग संचालन के प्रयोग के माध्यम से)

संक्षिप्त सारांश; जहां तक ​​परमाणुता चलती है, यह बहुत संभावना है कि आप जो भी कर रहे हैं उसे पढ़ने के लिए किसी भी विशेष निर्देश की आवश्यकता नहीं है ... हालांकि आप जो भी कर रहे हैं उसके आधार पर सावधान रहना आवश्यक है।

+0

ऐसा नहीं था कि 'अस्थिर' केवल "कंपाइलर जेनरेट" कैश के खिलाफ सुरक्षा करता है, जैसे कि रजिस्टर में पिछले मान को संग्रहीत करना? जिसका अर्थ है कि 'अस्थिर' अभी भी सीपीयू कैश के कारण बालों का डेटा उत्पन्न कर सकता है, और केवल 'इंटरलाक्ड' रीड का उपयोग करने से बाद वाले के खिलाफ सुरक्षा होगी। –

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