2016-03-03 4 views
22

अग्रिम में माफ़ी: यह सवाल एक उन्नत कोर, अपरिवर्तित सी ++ डेवलपर से आता है जो उन्नत सी # सीखने की कोशिश कर रहा है। निम्नलिखित पर विचार करें:सी # 6 है? (एल्विस सेशन) थ्रेड सुरक्षित? यदि हां, तो कैसे?

if (myUserDefinedObject != null) 
{ 
    myUserDefinedObject.ToString(); 
} 

यह स्पष्ट रूप से थ्रेड सुरक्षित नहीं है। दूसरी तरफ, मैंने दो ट्यूटोरियल देखे हैं जो कहते हैं? (उदाहरण के लिए अशक्त सशर्त ऑपरेटर या 'एल्विस ऑपरेटर'),

myUserDefinedObject?.ToString(); 

धागा सुरक्षित है। जब तक संकलक कवर (कंपकंपी) के नीचे एक [mutex?] लॉक नहीं करता है, मुझे समझ में नहीं आता कि यह कैसे सच हो सकता है। यदि यह मुहावरे धागा सुरक्षित है, तो क्या कोई मुझे तकनीकी विवरण के बारे में बता सकता है कि यह कैसे पूरा किया जाता है? यदि यह धागा सुरक्षित नहीं है, तो क्या किसी के पास ऐसा संदर्भ है जो वास्तव में कहता है कि यह नहीं है?

+3

क्षमा करें, लेकिन कोड का पहला ब्लॉक पूरी तरह से थ्रेड सुरक्षित हो सकता है, जिस संदर्भ में इसका उपयोग किया जाता है और इसमें शामिल चर के दायरे के आधार पर। –

+2

@ केनहाइट - मुझे लगता है कि पहले ब्लॉक के साथ विचार यह है कि एक और थ्रेड वैरिएबल को चेक के बाद 'शून्य' पर सेट कर सकता है, लेकिन 'टॉस्ट्रिंग()' कोड को असफल होने से पहले। मैं कहूंगा कि यह थ्रेड-सुरक्षित नहीं है। – Enigmativity

+0

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

उत्तर

24

MSDN (जोर मेरा) से:

अशक्त शर्त सदस्य पहुँच के लिए एक अन्य प्रयोग बहुत कम कोड के साथ एक धागा सुरक्षित तरीका में प्रतिनिधियों लागू कर रहा है। पुराने तरीके से निम्नलिखित की तरह कोड की आवश्यकता है:

var handler = this.PropertyChanged; 
if (handler != null) 
    handler(…) 

नया तरीका बहुत सरल है:

PropertyChanged?.Invoke(e) 

नया तरीका धागा सुरक्षित क्योंकि संकलक केवल PropertyChanged एक बार मूल्यांकन करने के लिए कोड उत्पन्न करता है, परिणाम को अस्थायी चर में रखते हुए।

तो यहां कोई लॉकिंग शामिल नहीं है - स्थानीय अस्थायी चर बनाकर थ्रेड-सुरक्षा लागू की जाती है, जो एक अलग धागे को शून्य जांच और कुछ अन्य ऑपरेशन के बीच उस चर को संशोधित करने से रोकती है।

+6

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

+0

मैं एमएसडीएन दस्तावेज पर विश्वास करने के लिए बहुत अधिक इच्छुक हूं अगर कोई यह बता सकता है कि सी # में, स्मृति स्मृति को गैर-शून्य के लिए जांचने के दौरान, और कुछ अज्ञात भविष्य के समय जब सामग्री तक पहुंचने का प्रयास किया जाता है उस पते के, उस सामग्री को संशोधित नहीं किया गया था। ऊपर दिए गए आलेख से, हम जानते हैं कि यह * हार्डवेयर * उस स्थान पर 'चिह्न' का उपयोग करके किया जा सकता है (परमाणुओं, स्मृति_मोड आदि का उपयोग करके)। क्या वह "कंपाइलर" कर रहा है? @ हांक, आपको भी एक उत्तर मिल सकता है - बस उस वस्तु से नहीं जिसे आप अभी भी उस स्थान पर होने की उम्मीद कर रहे थे। ;-) –

+3

यह वास्तव में धागा सुरक्षित नहीं है [यहां समझाया गया है] (https://msdn.microsoft.com/en-us/magazine/jj883956.aspx) "परिचय पढ़ें" अनुभाग देखें। जेआईटी कभी-कभी स्थानीय चर को पूरी तरह से खत्म कर सकता है और वास्तविक क्षेत्र में एक और पढ़ा सकता है। –

28

मैं बीजे मायर्स के (सही) उत्तर को स्पष्ट करना चाहता हूं।

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

if (this.SomeEvent != null) 
    this.SomeEvent(...); 

threadsafe नहीं है। मान को उत्परिवर्तित किया जा सकता है ताकि चेक के बाद यह शून्य न हो, चेक के बाद शून्य हो, और प्रोग्राम क्रैश हो जाए।

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

  • गैर अशक्त घटना धागा पर कैश हैंडलर एक
  • ईवेंट हैंडलर धागा पर अशक्त करने के लिए सेट
  • राज्य ईवेंट हैंडलर की जरूरत धागा पर नष्ट हो जाता है
  • ईवेंट हैंडलर पर चलता हो सकता है थ्रेड ए और भयंकर

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

मैं व्यक्तिगत रूप से प्लेग की तरह इस स्थिति से बचूंगा, लेकिन मैं सही मल्टीथ्रेड कोड लिखने के लिए पर्याप्त स्मार्ट नहीं हूं।

अब, वास्तविक प्रश्न के लिए के रूप में:

some_expression ?. ToString(); 

रूप

temp = some_expression 
temp == null ? null : temp.ToString() 

ही है उत्तरार्द्ध कोड "threadsafe" आपकी राय में है?

+0

यहां महान टिप्पणियां - आपके उत्कृष्ट स्पष्टीकरण के लिए धन्यवाद। "थ्रेड सुरक्षा" पूरी तरह से इस तरह निर्भर करता है कि धागे कोड का उपयोग कर रहे हैं। –

+0

तो ... सुरक्षित नहीं चल रहा है? या यह है? क्या हमें क्रैश से बचने के लिए लॉक का उपयोग करने की आवश्यकता है यदि हमारे पास कई धागे हैं जो आसपास गड़बड़ कर रहे हैं? – Narvalex

+4

@ नारवेलेक्स: मुझे कैसे पता होना चाहिए? समझाएं * जहां आप लॉक डाल रहे हैं *, और * लॉक किस दौड़ के खिलाफ रक्षा करता है *, और * डेडलॉक्स से बचने के लिए आपकी रणनीति क्या है *, और उसके बाद हम यह निर्धारित करने के लिए कुछ शॉट प्राप्त कर सकते हैं कि आपका समाधान सही है या नहीं। याद रखें, * थ्रेड सुरक्षा पूरे कार्यक्रमों की एक संपत्ति है *, इसलिए यदि आप जानना चाहते हैं कि कोई प्रोग्राम थ्रेडसेफ है, तो आपको पूरे कार्यक्रम की सटीकता प्रदान करनी होगी। * यही कारण है कि थ्रेडिंग कठिन है *। आप एक ईंट धारण कर रहे हैं और पूछ रहे हैं "क्या यह ईंट संरचनात्मक रूप से ध्वनि से बना है?" यह घर की संपत्ति है, न कि ईंटें। –

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