वाष्पशील बनाम इंटरलॉक्ड बनाम लॉक


670

मान लीजिए कि एक वर्ग में एक public int counterफ़ील्ड है जो कई थ्रेड्स द्वारा एक्सेस किया जाता है। यह intकेवल बढ़ा हुआ या घटा हुआ है।

इस क्षेत्र को बढ़ाने के लिए, किस दृष्टिकोण का उपयोग किया जाना चाहिए, और क्यों?

  • lock(this.locker) this.counter++;,
  • Interlocked.Increment(ref this.counter);,
  • की पहुँच संशोधक बदलें counterकरने के लिए public volatile

अब जब मैंने खोज लिया है volatile, तो मैं कई lockबयानों और उपयोग को हटा रहा हूं Interlocked। लेकिन क्या ऐसा न करने का एक कारण है?


C # संदर्भ में थ्रेडिंग पढ़ें । यह आपके प्रश्न के ins और outs को कवर करता है। तीनों में से प्रत्येक के अलग-अलग उद्देश्य और दुष्प्रभाव हैं।
स्पूल्सन

1
simple-talk.com/blogs/2012/01/24/… आप सरणियों में अस्थिरता के उपयोग को देख सकते हैं, मैं इसे पूरी तरह से नहीं समझता हूं, लेकिन यह इसके लिए एक संदर्भ है।
एरतन ओटजप

50
यह कहने के समान है कि "मुझे पता चला है कि स्प्रिंकलर सिस्टम कभी भी सक्रिय नहीं होता है, इसलिए मैं इसे हटाने जा रहा हूं और इसे धूम्रपान अलार्म से बदल दूंगा"। ऐसा नहीं करने का कारण यह है कि यह अविश्वसनीय रूप से खतरनाक है और आपको लगभग कोई लाभ नहीं देता है । यदि आपके पास कोड बदलने का समय है, तो इसे कम से कम गुणा करने का एक तरीका खोजें ! Multithreaded कोड को अधिक खतरनाक और आसानी से टूटने का एक तरीका मत ढूंढो!
एरिक लिपर्ट

1
मेरे घर में स्प्रिंकलर और स्मोक अलार्म दोनों हैं । जब एक थ्रेड पर एक काउंटर बढ़ाना और इसे दूसरे पर पढ़ना ऐसा लगता है जैसे आपको लॉक (या इंटरलॉक्ड) और वाष्पशील कीवर्ड दोनों की आवश्यकता है । सत्य?
योयो

2
@ योयो नहीं, आपको दोनों की आवश्यकता नहीं है।
डेविड श्वार्ट्ज

जवाबों:


858

सबसे खराब (वास्तव में काम नहीं करेगा)

की पहुँच संशोधक बदलें counterकरने के लिएpublic volatile

जैसा कि अन्य लोगों ने उल्लेख किया है, यह अपने आप में वास्तव में बिल्कुल भी सुरक्षित नहीं है। मुद्दा volatileयह है कि कई सीपीयू पर चलने वाले कई धागे डेटा और री-ऑर्डर निर्देशों को कैश और कर सकते हैं।

यदि यह नहीं है volatile , और सीपीयू ए मूल्य बढ़ाता है, तो सीपीयू बी वास्तव में कुछ समय बाद तक उस बढ़े हुए मूल्य को नहीं देख सकता है, जिससे समस्या हो सकती है।

यदि ऐसा है volatile, तो यह सुनिश्चित करता है कि दो सीपीयू एक ही समय में एक ही डेटा देखें। यह उन सभी को उनके रीड्स को इंटरलेय करने से रोकता नहीं है और उन ऑपरेशनों को लिखता है जो समस्या है जिससे आप बचने की कोशिश कर रहे हैं।

दूसरा सबसे अच्छा:

lock(this.locker) this.counter++;

यह करने के लिए सुरक्षित है (बशर्ते आप lockहर जगह जिसे आप एक्सेस करते हैं उसे याद रखें this.counter)। यह किसी भी अन्य धागे को किसी अन्य कोड को निष्पादित करने से रोकता है जो इसके द्वारा संरक्षित है locker। ताले का उपयोग करना, ऊपर के रूप में मल्टी-सीपीयू रीऑर्डरिंग समस्याओं को रोकता है, जो बहुत अच्छा है।

समस्या यह है कि, लॉकिंग धीमा है, और यदि आप lockerकिसी अन्य स्थान पर फिर से उपयोग करते हैं जो वास्तव में संबंधित नहीं है, तो आप बिना किसी कारण के अपने अन्य थ्रेड्स को अवरुद्ध कर सकते हैं।

श्रेष्ठ

Interlocked.Increment(ref this.counter);

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

मुझे पूरी तरह से यकीन नहीं है, लेकिन अगर यह अन्य सीपीयू को पुनः व्यवस्थित करने वाली चीजों के आसपास हो जाता है, या यदि आपको वेतन वृद्धि के साथ अस्थिरता को भी संयोजित करने की आवश्यकता है।

InterlockedNotes:

  1. इंटरलेक्ट किए गए तरीके कॉरपोरेट या सीपीयू के किसी भी नंबर पर सुरक्षित रूप से सुरक्षित हैं।
  2. इंटरलॉक की गई विधियाँ उनके द्वारा निष्पादित किए जाने वाले निर्देशों के चारों ओर एक पूर्ण बाड़ लगाती हैं, इसलिए पुनरावृत्ति नहीं होती है।
  3. इंटरलॉक्ड तरीकों की जरूरत नहीं है या यहां तक ​​कि एक अस्थिर क्षेत्र तक पहुंच का समर्थन नहीं करते हैं , क्योंकि अस्थिर को दिए गए क्षेत्र पर संचालन के चारों ओर एक आधा बाड़ रखा जाता है और इंटरलॉक किया गया पूर्ण बाड़ का उपयोग कर रहा है।

फुटनोट: वाष्पशील वास्तव में किसके लिए अच्छा है।

जैसा कि volatileइस प्रकार के बहुस्तरीय मुद्दों को रोकता नहीं है, इसके लिए क्या है? एक अच्छा उदाहरण कह रहा है कि आपके पास दो धागे हैं, एक जो हमेशा एक चर (लिख queueLength) को लिखता है , और एक जो हमेशा उसी चर से पढ़ता है।

यदि queueLengthअस्थिर नहीं है, तो थ्रेड A पांच बार लिख सकता है, लेकिन थ्रेड बी उन राइट्स को विलंबित (या गलत तरीके से भी संभावित) के रूप में देख सकता है।

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


29
"मुझे पूरी तरह से यकीन नहीं है ... अगर आपको वेतन वृद्धि के साथ अस्थिरता को संयोजित करने की आवश्यकता है।" उन्हें AFAIK से जोड़ा नहीं जा सकता है, क्योंकि हम रेफ द्वारा अस्थिर नहीं कर सकते हैं। वैसे शानदार जवाब।
होसम ऐली

41
बहुत धन्यवाद! "क्या वाष्पशील वास्तव में अच्छा है" पर आपका फुटनोट वह है जो मैं देख रहा था और पुष्टि करता था कि मैं कैसे वाष्पशील का उपयोग करना चाहता हूं।
जैक्स बॉश

7
दूसरे शब्दों में, यदि किसी संस्करण को अस्थिर के रूप में घोषित किया जाता है, तो संकलक यह मान लेगा कि जब भी आपका कोड इसके पार आता है, तो संस्करण का मान समान नहीं रहेगा। तो एक लूप में जैसे: जबकि (m_Var) {}, और m_Var को एक और धागे में गलत सेट किया जाता है, कंपाइलर यह जांच नहीं करेगा कि पहले से ही रजिस्टर में क्या है जो पहले m_Var के मान से भरा हुआ था, लेकिन m_Var से मान को पढ़ता है फिर। हालांकि, इसका मतलब यह नहीं है कि अस्थिर घोषित नहीं करने के कारण लूप असीम रूप से चलेगा - अस्थिर को निर्दिष्ट करने की गारंटी केवल यह है कि यह नहीं होगा यदि m_Var को किसी अन्य थ्रेड में गलत पर सेट किया गया है।
जाच सॉ

35
@Zach देखा: C ++ के लिए मेमोरी मॉडल के तहत, वाष्पशील है कि आपने इसे कैसे वर्णित किया है (मूल रूप से डिवाइस-मैप्ड मेमोरी के लिए उपयोगी है और बहुत कुछ नहीं)। सीएलआर के लिए मेमोरी मॉडल के तहत (इस सवाल को C # टैग किया गया है) यह है कि वाष्पशील, मेमोरी स्टोरेज के आसपास मेमोरी बैरियर लगाएगा और उस स्टोरेज लोकेशन को लिख देगा। मेमोरी बाधाओं (और कुछ विधानसभा निर्देशों के विशेष लॉक किए गए विविधताएं) क्या आप प्रोसेसर को चीजों को फिर से चालू नहीं करने के लिए कहते हैं, और वे काफी महत्वपूर्ण हैं ...
ओरियन एडवर्ड्स

19
@ZachSaw: C # में एक अस्थिर क्षेत्र C # कंपाइलर और jit कंपाइलर को कुछ अनुकूलन करने से रोकता है जो मूल्य को कैश करेगा। यह इस बात की भी निश्चित गारंटी देता है कि जो आदेश पढ़ता है और लिखता है, उसे कई थ्रेड्स में देखा जा सकता है। कार्यान्वयन विवरण के रूप में, यह पठन और लेखन पर मेमोरी बाधाओं को शुरू करके ऐसा कर सकता है। गारंटीकृत सटीक शब्दार्थ विनिर्देश में वर्णित हैं; ध्यान दें कि विनिर्देश करता नहीं है कि एक गारंटी संगत के आदेश सभी अस्थिर राईट और पढ़ने से निगरानी की जाएगी सभी धागे।
एरिक लिपिपर्ट

147

संपादित करें: जैसा कि टिप्पणियों में उल्लेख किया गया है, इन दिनों मैं Interlockedएक एकल चर के मामलों के लिए उपयोग करने में प्रसन्न हूं जहां यह स्पष्ट रूप से ठीक है। जब यह अधिक जटिल हो जाता है, तो मैं अभी भी ताला लगाने के लिए वापस आऊंगा ...

volatileजब आपको वेतन वृद्धि की आवश्यकता होती है, तो इसका उपयोग नहीं किया जाएगा - क्योंकि पढ़ने और लिखने के अलग-अलग निर्देश हैं। आपके द्वारा पढ़ा जाने के बाद एक और धागा मूल्य बदल सकता है लेकिन इससे पहले कि आप वापस लिखें।

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


16
मुझे अब से लॉक-फ्री कोडिंग के बारे में भूलना सुनिश्चित करने के लिए +1।
ज़ाक्रॉन

5
लॉक-फ़्री कोड निश्चित रूप से लॉक-फ़्री नहीं होते हैं क्योंकि वे किसी चरण में लॉक होते हैं - चाहे (एफएसबी) बस या इंटरकैप स्तर पर हो, फिर भी कोई जुर्माना देना होगा। हालाँकि इन निचले स्तरों पर ताला लगाना आम तौर पर तब तक तेज़ होता है जब तक आप बैंडविड्थ को संतृप्त नहीं करते जहाँ ताला होता है।
जच सॉ

2
इंटरलॉक के साथ कुछ भी गलत नहीं है, यह वही है जो आपकी तलाश में है और एक पूर्ण ताला () की तुलना में तेज है
जैप

5
@ जाप: हां, इन दिनों मैं एक वास्तविक सिंगल काउंटर के लिए इंटरलॉक का उपयोग करूंगा । मैं बस चर के लिए कई लॉक-फ्री अपडेट के बीच बातचीत को बाहर करने की कोशिश करने के आसपास गड़बड़ शुरू नहीं करना चाहता ।
जॉन स्कीट

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

44

" volatile" प्रतिस्थापित नहीं करता है Interlocked.Increment! यह सिर्फ यह सुनिश्चित करता है कि चर को कैश नहीं किया गया है, लेकिन सीधे उपयोग किया जाता है।

एक चर में वृद्धि वास्तव में तीन आपरेशनों की आवश्यकता है:

  1. पढ़ना
  2. वेतन वृद्धि
  3. लिखो

Interlocked.Increment एक परमाणु संचालन के रूप में सभी तीन भागों करता है।


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

1
वास्तव में, volatileयह सुनिश्चित नहीं करता है कि चर कैश नहीं है। यह सिर्फ इस पर प्रतिबंध लगाता है कि इसे कैसे कैश किया जा सकता है। उदाहरण के लिए, यह अभी भी सीपीयू के एल 2 कैश की चीजों में कैश्ड हो सकता है क्योंकि वे हार्डवेयर में सुसंगत हैं। यह अभी भी पूर्वनिर्मित किया जा सकता है। राइट अभी भी कैश करने के लिए पोस्ट किया जा सकता है, और इसी तरह। (जो मुझे लगता है कि Zach में क्या हो रहा था।)
डेविड श्वार्ट्ज

42

या तो लॉक या इंटरलॉक की गई वृद्धि वह है जिसे आप ढूंढ रहे हैं।

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

जैसे

while (m_Var)
{ }

यदि m_Var को किसी अन्य थ्रेड में गलत पर सेट किया गया है, लेकिन इसे अस्थिर नहीं घोषित किया गया है, तो कंपाइलर इसे एक अनन्त लूप बनाने के लिए स्वतंत्र है (लेकिन इसका मतलब यह नहीं है कि यह सीपीयू रजिस्टर के खिलाफ जाँच करके बना होगा) m_Var को बहुत शुरुआत से प्राप्त किया गया था) m_Var की मेमोरी लोकेशन पर एक और रीड जारी करने के बजाय (यह कैश किया जा सकता है - हमें नहीं पता और परवाह नहीं है और यह x86 / x64 के कैश सुसंगतता का बिंदु है)। अन्य सभी पोस्ट जो पहले निर्देश पुनर्मूल्यांकन का उल्लेख करते थे, वे दिखाते हैं कि वे x86 / x64 आर्किटेक्चर को नहीं समझते हैं। अस्थिर नहीं करता हैसमस्याएँ पढ़ें / लिखें बाधाओं के रूप में पहले के पदों से यह कहते हुए कि 'यह पुन: व्यवस्थित होने से रोकता है'। वास्तव में, एमईएसआई प्रोटोकॉल के लिए फिर से धन्यवाद, हम गारंटी देते हैं कि हम जो पढ़ा है वह हमेशा सीपीयू में समान है चाहे वास्तविक परिणाम भौतिक मेमोरी में रिटायर हो गए हैं या बस स्थानीय सीपीयू के कैश में रहते हैं। मैं इसके विवरण में बहुत दूर नहीं जाऊंगा, लेकिन यह आश्वासन दिया जाता है कि अगर यह गलत हो जाता है, तो इंटेल / एएमडी संभवतः एक प्रोसेसर को याद करेगा! इसका मतलब यह भी है कि हमें ऑर्डर निष्पादन आदि से ध्यान हटाने की ज़रूरत नहीं है। परिणाम हमेशा आदेश में रिटायर होने की गारंटी है - अन्यथा हम भरवां हैं!

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

वाष्पशील होने के साथ, आप अभी भी सिर्फ 1 निर्देश के साथ समाप्त करेंगे (यह मानते हुए जेआईटी कुशल है) - inc dword ptr [m_Var]। हालाँकि, प्रोसेसर (cpuA) कैश लाइन के अनन्य स्वामित्व के लिए नहीं कहता है, जबकि यह सब इंटरलॉक किए गए संस्करण के साथ किया गया है। जैसा कि आप कल्पना कर सकते हैं, इसका मतलब यह है कि सीपीयू द्वारा पढ़ने के बाद अन्य प्रोसेसर m_Var में एक अद्यतन मान वापस लिख सकते हैं। इसलिए अब दो बार मूल्य वृद्धि करने के बजाय, आप बस एक बार समाप्त करते हैं।

उम्मीद है कि इस मुद्दे को साफ करता है।

अधिक जानकारी के लिए, 'मल्टीथ्रेड एप्स में कम-लॉक तकनीक के प्रभाव को समझें' - http://msdn.microsoft.com/en-au/magazine/cc163715.aspx

ps क्या यह बहुत देर से जवाब दिया? सभी उत्तर इतने स्पष्ट रूप से गलत थे (विशेष रूप से एक उत्तर के रूप में चिह्नित) उनके स्पष्टीकरण में मुझे सिर्फ इसे पढ़ने वाले किसी अन्य व्यक्ति के लिए स्पष्ट करना था। कहते हैं

pps मैं मान रहा हूँ कि लक्ष्य x86 / x64 है और IA64 नहीं है (इसका एक अलग मेमोरी मॉडल है)। ध्यान दें कि Microsoft का ECMA चश्मा इस प्रकार खराब हो जाता है कि यह सबसे मजबूत मेमोरी मॉडल के बजाय सबसे मजबूत मेमोरी को निर्दिष्ट करता है (यह सबसे मजबूत मेमोरी मॉडल के खिलाफ निर्दिष्ट करना हमेशा बेहतर होता है, इसलिए यह पूरे प्लेटफॉर्म के अनुरूप है - अन्यथा कोड जो x86 / 24 के लिए 24-7 रन होगा) X64 IA64 पर बिल्कुल नहीं चल सकता है, हालांकि Intel ने IA64 के लिए समान रूप से मजबूत मेमोरी मॉडल लागू किया है) - Microsoft ने खुद यह स्वीकार किया - http://blogs.msdn.com/b/cbrumme/archive/2003/05/17/51445.aspx


3
दिलचस्प। क्या आप इसका संदर्भ दे सकते हैं? मैं ख़ुशी से इसे वोट करूँगा, लेकिन कुछ आक्रामक जवाब के साथ कुछ आक्रामक भाषा के साथ पोस्ट करना जो मेरे द्वारा पढ़े गए संसाधनों के अनुरूप है, थोड़ा और ठोस सबूत की आवश्यकता है।
स्टीवन एवर्स

यदि आप इंगित कर सकते हैं कि आप किस हिस्से को संदर्भित करना चाहते हैं, तो मुझे कहीं से कुछ सामान खोदने में खुशी होगी (मुझे अत्यधिक संदेह है कि मैंने कोई x86 / x64 विक्रेता व्यापार रहस्य दूर दिए हैं, इसलिए इन्हें विकी, इंटेल से आसानी से उपलब्ध होना चाहिए PRMs (प्रोग्रामर के संदर्भ मैनुअल), MSFT ब्लॉग, MSDN या कुछ इसी तरह के) ...
Zach Saw

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

4
हां, आप जो कुछ भी कहते हैं वह 100% कम से कम 99% अंक पर नहीं है। जब आप काम पर विकास की दौड़ में होते हैं तो यह साइट (ज्यादातर) बहुत उपयोगी होती है लेकिन दुर्भाग्य से वोटों के खेल के अनुरूप उत्तरों की सटीकता नहीं होती है। तो मूल रूप से स्टैकओवरफ्लो में आप महसूस कर सकते हैं कि पाठकों की लोकप्रिय समझ क्या नहीं है कि यह वास्तव में क्या है। कभी-कभी शीर्ष उत्तर सिर्फ शुद्ध अस्पष्ट - तरह के मिथक होते हैं। और दुर्भाग्य से यह वही है जो समस्या को हल करते समय पढ़ने वाले लोगों में आता है। हालांकि यह समझ में आता है, कोई भी सब कुछ नहीं जान सकता।
user1416420

1
@BenVoigt मैं जा सकता हूं और सभी आर्किटेक्चर के बारे में जवाब दे सकता हूं। .NET चलता है, लेकिन यह कुछ पेज लेगा और निश्चित रूप से एसओ के लिए उपयुक्त नहीं है। लोगों द्वारा मनमाने ढंग से उपयोग किए जाने वाले नेट अंतर्निहित हार्डवेयर मेम-मॉडल के आधार पर लोगों को शिक्षित करना कहीं बेहतर है। और मेरी टिप्पणियों 'हर जगह' के साथ, मैं उन गलतियों को ठीक कर रहा था जो लोग कैश फ्लशिंग / अमान्य करने आदि में कर रहे थे। उन्होंने हार्डवेयर को निर्दिष्ट किए बिना अंतर्निहित हार्डवेयर के बारे में धारणाएं बनाईं।
ज़च सॉ ने

16

इंटरलॉक किए गए कार्य लॉक नहीं होते हैं। वे परमाणु हैं, जिसका अर्थ है कि वे वेतन वृद्धि के दौरान एक संदर्भ स्विच की संभावना के बिना पूरा कर सकते हैं। इसलिए गतिरोध या प्रतीक्षा का कोई मौका नहीं है।

मैं कहूंगा कि आपको इसे हमेशा लॉक और इन्क्रीमेंट के लिए पसंद करना चाहिए।

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

यह एक बहुत अच्छा लेख है यदि आप लॉक-फ्री कोड के बारे में अधिक पढ़ना चाहते हैं, और इसे लिखने के लिए सही तरीका है

http://www.ddj.com/hpc-high-performance-computing/210604448


11

लॉक (...) काम करता है, लेकिन एक थ्रेड को ब्लॉक कर सकता है, और गतिरोध पैदा कर सकता है यदि अन्य कोड असंगत तरीके से एक ही ताले का उपयोग कर रहा है।

इंटरलॉक किया गया। * इसे करने का सही तरीका है ... आधुनिक सीपीयू के रूप में बहुत कम ओवरहेड एक आदिम के रूप में इसका समर्थन करता है।

अपने आप में अस्थिरता सही नहीं है। एक थ्रेड को फिर से प्राप्त करने और फिर से लिखने का प्रयास करने वाला एक धागा अभी भी एक और धागा के साथ संघर्ष कर सकता है।


8

मैंने यह देखने के लिए कुछ परीक्षण किया कि सिद्धांत वास्तव में कैसे काम करता है: kennethxu.blogspot.com/2009/05/interlocked-vs-monitor-performance.html । मेरा परीक्षण तुलनात्मक अभ्यास पर अधिक केंद्रित था लेकिन वृद्धि के लिए परिणाम समान है। मल्टी-सीपीयू वातावरण में इंटरलॉकिंग तेजी से आवश्यक नहीं है। यहां 2 साल पुराने 16 सीपीयू सर्वर पर इन्क्रीमेंट का परीक्षा परिणाम है। यह ध्यान में रखें कि परीक्षण में वृद्धि के बाद सुरक्षित पढ़ा जाना भी शामिल है, जो वास्तविक दुनिया में विशिष्ट है।

D:\>InterlockVsMonitor.exe 16
Using 16 threads:
          InterlockAtomic.RunIncrement         (ns):   8355 Average,   8302 Minimal,   8409 Maxmial
    MonitorVolatileAtomic.RunIncrement         (ns):   7077 Average,   6843 Minimal,   7243 Maxmial

D:\>InterlockVsMonitor.exe 4
Using 4 threads:
          InterlockAtomic.RunIncrement         (ns):   4319 Average,   4319 Minimal,   4321 Maxmial
    MonitorVolatileAtomic.RunIncrement         (ns):    933 Average,    802 Minimal,   1018 Maxmial

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

@Zach, थ्रेड सुरक्षित तरीके से काउंटर बढ़ाने के परिदृश्य के बारे में यहां कैसे चर्चा हुई। आपके दिमाग में अन्य उपयोग परिदृश्य क्या था या आप इसे कैसे परखेंगे? टिप्पणी के लिए धन्यवाद BTW।
केनेथ जू

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

2
इसे फिर से देखना। यदि असली अड़चन FSB के साथ है, तो मॉनिटर कार्यान्वयन को उसी अड़चन का निरीक्षण करना चाहिए। वास्तविक अंतर यह है कि इंटरलाक्ड व्यस्त प्रतीक्षा और पुन: प्रयास कर रहा है जो उच्च प्रदर्शन की गिनती के साथ एक वास्तविक मुद्दा बन जाता है। कम से कम मुझे उम्मीद है कि मेरी टिप्पणी इस बात का ध्यान दिलाती है कि इंटरलॉकिंग हमेशा गिनती के लिए सही विकल्प नहीं है। तथ्य यह है कि लोग विकल्प देख रहे हैं अच्छी तरह से समझाया। आपको एक लंबे योजक gee.cs.oswego.edu/dl/jsr166/dist/jsr166edocs/jsr166e/…
केनेथ जू

8

3

मैं अंतर के बीच अन्य उत्तर में उल्लेख करने के लिए जोड़ना चाहते हैं volatile, Interlockedऔर lock:

वाष्पशील कीवर्ड को इन प्रकारों के क्षेत्रों में लागू किया जा सकता है :

  • संदर्भ प्रकार।
  • सूचक प्रकार (एक असुरक्षित संदर्भ में)। ध्यान दें कि यद्यपि सूचक स्वयं अस्थिर हो सकता है, वह वस्तु जिसे वह इंगित नहीं कर सकता है। दूसरे शब्दों में, आप "सूचक" को "अस्थिर" घोषित नहीं कर सकते।
  • जैसे सरल प्रकार sbyte, byte, short, ushort, int, uint, char, float, और bool
  • निम्नलिखित आधार प्रकारों में से एक के साथ एक enum के प्रकार: byte, sbyte, short, ushort, int, या uint
  • सामान्य प्रकार के पैरामीटर जिन्हें संदर्भ प्रकार के रूप में जाना जाता है।
  • IntPtrऔर UIntPtr

अन्य प्रकारों , जिनमें शामिल हैं doubleऔर long, "अस्थिर" के रूप में चिह्नित नहीं किए जा सकते क्योंकि उन प्रकारों के क्षेत्रों को पढ़ना और लिखना परमाणु होने की गारंटी नहीं दी जा सकती है। उन प्रकार के क्षेत्रों में बहु-थ्रेडेड एक्सेस की सुरक्षा के लिए, Interlockedक्लास सदस्यों का उपयोग करें या lockस्टेटमेंट का उपयोग करके एक्सेस की रक्षा करें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.