2008-12-09 5 views
26

"कोड पुन: प्रवेश" और "थ्रेड सुरक्षा" की अवधारणाओं के बीच क्या अंतर है? नीचे उल्लिखित लिंक के अनुसार, उनमें से एक या उनमें से कोई भी कोड का एक टुकड़ा नहीं हो सकता है।कोड पुन: प्रवेश द्वितीय थ्रेड सुरक्षा

Reentrant and Thread safe code

मैं स्पष्ट रूप से explaination को समझने में सक्षम नहीं था। मदद की सराहना की जाएगी।

उत्तर

21

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

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

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

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

+3

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

+1

आप सही हैं - जैसा कि आप नीचे कहते हैं, आपको बाद के उदाहरण के लिए संकेतों को प्रभावी ढंग से पुन: प्रवेश करने के लिए भी अक्षम करना होगा। – ConcernedOfTunbridgeWells

+0

@ConcernedOfTunbridgeWells, यदि एक func अंदर ढेर का उपयोग करता है, तो यह एक अच्छा मौका है कि यह func पुनः प्रवेश नहीं है। क्यूं कर? – Alcott

8

कि लेख का कहना है:

"एक समारोह या तो रैत्रांत, धागा सुरक्षित, दोनों, या न हो सकता है।"

यह भी कहते हैं:

"गैर रैत्रांत कार्यों धागा असुरक्षित हैं"।

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

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

take_global_lock(); 
int i = get_global_counter(); 
do_callback(i); 
set_global_counter(i+1); 
release_global_lock(); 

हैं, तो एक और कॉलबैक में जिसके परिणामस्वरूप, तो कॉलबैक के दोनों स्तरों में एक ही पैरामीटर मिल जाएगा (जो ठीक हो सकता है: यह वैश्विक काउंटर बढ़ाने के लिए, और कॉलबैक प्रदर्शन करने के लिए माना जाता है एपीआई के आधार पर), लेकिन काउंटर केवल एक बार बढ़ाया जाएगा (जो लगभग निश्चित रूप से एपीआई नहीं है जिसे आप चाहते हैं, इसलिए इसे प्रतिबंधित करना होगा)।

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

यहाँ कुछ छद्म कोड है जो "दुर्बलता से फिर से प्रवेशी" लेकिन नहीं थ्रेड-सुरक्षित है:

int i = get_global_counter(); 
do_callback(i); 
set_global_counter(get_global_counter()+1); 

अब यह कॉलबैक से समारोह कॉल करने के लिए ठीक है, लेकिन यह समारोह समवर्ती कॉल करने के लिए सुरक्षित नहीं है विभिन्न धागे से। सिग्नल हैंडलर से इसे कॉल करना भी सुरक्षित नहीं है, क्योंकि संकेत सिग्नल हैंडलर से फिर से प्रवेश करना सही समय पर होने पर सिग्नल हो सकता है। तो कोड उचित परिभाषा द्वारा गैर-पुन: प्रवेशकर्ता है।

यहां कुछ कोड है जो तर्कसंगत रूप से पूरी तरह से पुनः प्रवेश करने वाला है (सिवाय इसके कि मुझे लगता है कि मानक पुनर्विक्रेता और 'सिग्नल द्वारा गैर-बाधा' के बीच अंतर करता है, और मुझे यकीन नहीं है कि यह कहां गिरता है), लेकिन अभी भी धागा नहीं है- सुरक्षित:

int i = get_global_counter(); 
do_callback(i); 
disable_signals(); // and any other kind of interrupts on your system 
set_global_counter(get_global_counter()+1); 
restore_signal_state(); 

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

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

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