2012-01-04 8 views
12

क्या मुझे सही ढंग से समझ आया है कि सभी धागे में अपने स्वयं के ढेर में विधि के चर की प्रतिलिपि है, इसलिए अलग-अलग धागे से स्थिर विधि कहने पर समस्या नहीं होगी?सी # कक्षा का उपयोग करते समय केवल स्थिर विधियों और कोई चर के साथ समवर्ती समस्याएं हो सकती हैं?

+0

यदि यह कड़ाई से है - * शायद *। लेकिन यह एक बहुत ही रोचक विधि की तरह नहीं लगता है। – Yuck

+0

मेरा मानना ​​है कि उदाहरण के विपरीत जब समस्याएं होती हैं तो आपके पास एक सार्वजनिक कक्षा हो सकती है जिसके पास स्टेटिक विधियों तक पहुंच हो सकती है, क्या आप कोड का एक उदाहरण दे सकते हैं जो वास्तव में आपके भ्रम की बात है ..? – MethodMan

+0

आपको यह उपयोगी मिल सकता है: http://csharpindepth.com/Articles/General/Singleton.aspx – David

उत्तर

16

हां और नहीं। यदि पैरामीटर मान प्रकार हैं, तो हाँ उनके पास अपनी प्रतियां हैं। या यदि संदर्भ प्रकार अपरिवर्तनीय है, तो इसे बदला नहीं जा सकता है और आपके पास कोई समस्या नहीं है। हालांकि, यदि पैरामीटर म्यूटेबल संदर्भ प्रकार हैं, तो अभी भी संभव थ्रेड सुरक्षा समस्याएं हैं जिन पर तर्क पारित होने के साथ विचार किया जा सकता है।

क्या यह समझ में आता है? यदि आप एक संदर्भ प्रकार को तर्क के रूप में पास करते हैं, तो इसका संदर्भ "मान द्वारा" पारित किया जाता है, इसलिए यह एक नया संदर्भ है जो पुरानी वस्तु को संदर्भित करता है। इस प्रकार आप दो अलग-अलग धागे संभावित रूप से एक ही वस्तु को गैर-थ्रेड-सुरक्षित तरीके से बदल सकते हैं।

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

+0

+1 यह नोट करने के लिए कि स्थैतिक (या इसकी कमी) का उपयोग कुछ भी गारंटी नहीं देता है- समान नियम गैर स्थैतिक तरीकों के लिए होते हैं। –

+0

धन्यवाद! यह मेरा काम बहुत आसान बनाता है। –

+0

@ क्रिसशैन: बहुत सच है, मुझे स्पष्ट रूप से उल्लेख करना चाहिए था कि, मुझे उम्मीद थी कि यह निहित था। –

2

ऐसी कोई गारंटी नहीं है जब तक कि सभी चर अपरिवर्तनीय संदर्भ प्रकार या मूल्य प्रकार न हों।

यदि चर परिवर्तनीय संदर्भ प्रकार हैं, तो उचित सिंक्रनाइज़ेशन करने की आवश्यकता है।

संपादित करें: परिवर्तनीय चर केवल सिंक्रनाइज़ किए जाने की आवश्यकता है यदि उन्हें धागे के बीच साझा किया जाता है- स्थानीय रूप से घोषित म्यूटेबल जिन्हें विधि के बाहर प्रकट नहीं किया जाता है, को सिंक्रनाइज़ नहीं किया जाना चाहिए।

+0

म्यूटेबल संदर्भ घोषित और स्थानीय रूप से उपयोग किए जाने के लिए सिंक्रनाइज़ेशन की आवश्यकता नहीं है। – Tudor

+0

सच है, तदनुसार संपादित करेंगे। –

0

हाँ, जब तक कि तरीकों केवल स्थानीय गुंजाइश चर और किसी भी gloval चर का उपयोग, इसलिए वहाँ कोई किसी भी तरह से कि तरीकों में से किसी भी किसी भी वस्तु की स्थिति पर प्रतिकूल प्रभाव पड़ सकता है, अगर यह true है, तो आप multithreading में इसका उपयोग करने में कोई समस्या नहीं है। मैं कहूंगा कि, इस स्थिति में, static वे या नहीं, प्रासंगिक नहीं हैं।

0

यदि वे विधि के लिए स्थानीय चर हैं तो हाँ, आपके पास चिंता करने की कोई बात नहीं है। बस सुनिश्चित करें कि आप संदर्भ के आधार पर पैरामीटर पारित नहीं कर रहे हैं या वैश्विक चर का उपयोग नहीं कर रहे हैं और उन्हें विभिन्न धागे में बदल रहे हैं। तब आप परेशानी में होंगे।

0

static विधियां static फ़ील्ड में डेटा को संदर्भित कर सकती हैं - या तो अपनी कक्षा में या उसके बाहर - जो थ्रेड सुरक्षित नहीं हो सकती है।

तो आखिरकार आपके प्रश्न का उत्तर "नहीं" है, क्योंकि समस्याएं हो सकती हैं, हालांकि आम तौर पर वहां नहीं होगा।

0

दो धागे एक ही ऑब्जेक्ट पर या तो पैरामीटर के रूप में अलग-अलग धागे पर विधियों में पारित होने वाले ऑब्जेक्ट द्वारा संचालित करने में सक्षम होना चाहिए, या यदि ऑब्जेक्ट के माध्यम से वैश्विक रूप से किसी ऑब्जेक्ट को एक्सेस किया जा सकता है या सभी बेटों की तरह बंद हो जाती है।

मार्क

9

मैं सही ढंग से समझ गया कि सभी धागे को अपने स्वयं के ढेर में विधि के चर के प्रति है तो वहाँ समस्याओं जब एक स्थिर विधि अलग धागे से कहा जाता है नहीं होगा है?

सं

सबसे पहले, यह गलत है कि "सभी धागे को अपने स्वयं के ढेर में विधि के स्थानीय चर की एक प्रति है।" एक स्थानीय चर केवल स्टैक पर उत्पन्न होता है जब इसका जीवनकाल कम होता है; स्थानीय चरों में मनमाने ढंग से लंबे जीवनकाल हो सकते हैं यदि वे (1) बंद-बाहरी बाहरी चर, (2) एक पुनरावर्तक ब्लॉक में घोषित किए गए हैं, या (3) एसिंक विधि में घोषित किए गए हैं।

उन सभी मामलों में एक थ्रेड पर एक विधि के सक्रियण द्वारा बनाई गई स्थानीय चर को बाद में कई धागे द्वारा उत्परिवर्तित किया जा सकता है। ऐसा करना थ्रेडसेफ नहीं है।

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

सी # कक्षा का उपयोग करते समय केवल स्थिर तरीकों और कोई चर के साथ समवर्ती समस्याएं हो सकती हैं?

मुझे लगता है कि आपका मतलब है "कोई स्थैतिक चर नहीं" और "कोई स्थानीय चर नहीं"।

बिल्कुल हो सकता है। उदाहरण के लिए, यहां कोई स्थैतिक चर नहीं है, कोई गैर स्थैतिक तरीकों, दूसरे थ्रेड से अलग कोई ऑब्जेक्ट नहीं बनाया गया है, और एक स्थानीय चर वैरिएबल का संदर्भ रखने के लिए है। वास्तव में के अलावा अन्य तरीकों में से कोई भी पर कुछ भी नहीं करता है। यह प्रोग्राम deadlocks। आप यह नहीं मान सकते कि सिर्फ इसलिए कि आपका प्रोग्राम मर चुका है कि इसमें कोई थ्रेडिंग बग नहीं है!

पाठक के लिए व्यायाम: वर्णन करें कि इस प्रोग्राम में वास्तव में कोई ताले नहीं हैं।

class MyClass 
{ 
    static MyClass() 
    { 
     // Let's run the initialization on another thread! 
     var thread = new System.Threading.Thread(Initialize); 
     thread.Start(); 
     thread.Join(); 
    } 

    static void Initialize() 
    { /* TODO: Add initialization code */ } 

    static void Main() 
    { } 
} 

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

+2

किसी भी स्थैतिक सदस्यों (इस मामले में 'आरंभिक' विधि) को निष्पादित करने की अनुमति देने से पहले स्थिर सीटीआर को पूरा करने की गारंटी है, लेकिन सीटीओ उस थ्रेड के लिए इंतजार कर रहे थ्रेड के लिए प्रतीक्षा में व्यस्त है। –

+0

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

+0

उचित लगता है। मृत लॉक मुद्दा [एमएसडीएन पेज] (http://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx) से स्पष्ट नहीं है, लेकिन [सी # विनिर्देश 17.11] (http: //www.ecma -international.org/publications/files/ECMA-ST/Ecma-334.pdf) कम से कम "किसी दिए गए एप्लिकेशन डोमेन में" एक बार नोट करके संकेत देते हैं। –

0

स्थिर तरीकों के लिए आवश्यक रूप से थ्रेड-सुरक्षित क्यों नहीं हैं, इस बारे में उत्तर के रूप में, यह विचार करने योग्य है कि वे क्यों हो सकते हैं, और वे अक्सर क्यों होते हैं।

public static int Max(int x, int y) 
{ 
    return x > y ? x : y; 
} 

यह शुद्ध समारोह धागा सुरक्षित है कोई रास्ता नहीं इस पर कोड को प्रभावित करने के लिए है, क्योंकि:

पहले कारण है कि वे हो सकता है, मामले की तरह आप के बारे में सोच रहे थे मुझे लगता है, कोई अन्य धागा, स्थानीय x और y वे हैंडल के लिए स्थानीय रहते हैं, किसी साझा स्थान में संग्रहीत नहीं होते हैं, एक प्रतिनिधि में कब्जा नहीं किया जाता है, या अन्यथा पूरी तरह से स्थानीय संदर्भ छोड़ते हैं।

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

एक स्थिर विधि भी गारंटी कर सकते हैं अपने आप धागे की सुरक्षा:

public object GetCachedEntity(string key) 
{ 
    object ret; //local and remains so. 
    lock(_cache) //same lock used on every operation that deals with _cache; 
    return _cache.TryGetValue(key, out ret) ? ret : null; 
} 

या:

public object GetCachedEntity(string key) 
{ 
    object ret; 
    return _cache.TryGetValue(key, out ret) ? ret : null; //_cache is known to be thread-safe in itself! 
} 
बेशक

यहाँ इस एक उदाहरण सदस्य जो दूसरे से भ्रष्टाचार के खिलाफ खुद की रक्षा करता है से अलग नहीं है धागे (उन सभी अन्य कोडों के साथ सह-संचालन करके जो वे साझा करते हैं) से संबंधित हैं।

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

कारणों दो गुना कर रहे हैं:

  1. संचालन की तरह सबसे अधिक स्थिर सदस्यों के लिए उपयोगी होते हैं या तो शुद्ध कार्य (Math वर्ग के स्थिर के अधिकांश सदस्य, उदाहरण के लिए) या स्थिर पढ़ा पढ़ा केवल वही चर जो अन्य धागे द्वारा नहीं बदला जाएगा।

  2. किसी तीसरे पक्ष के स्थिर सदस्यों को अपना स्वयं का सिंक्रनाइज़ेशन लाने में बहुत मुश्किल है।

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

हालांकि, मैं स्थिर सदस्यों से निपट रहा हूं जो थ्रेड-सुरक्षित नहीं हैं, यह मेरे लिए ऐसा करना बहुत कठिन है। दरअसल, इस बात पर विचार करते हुए कि मैं सिर्फ अपने कोड के साथ नहीं दौड़ सकता, लेकिन अन्य पार्टियों के कोड के साथ, यह असंभव हो सकता है। इससे बेकार के बगल में ऐसा कोई सार्वजनिक स्थैतिक सदस्य बन जाएगा।

विडंबना यह है कि स्थिर सदस्य थ्रेड-सुरक्षित होने का कारण यह नहीं है कि उन्हें ऐसा करना आसान हो (हालांकि यह शुद्ध कार्यों को कवर करता है), लेकिन यह कठिन है! इतना मुश्किल है कि कोड के लेखक को उपयोगकर्ता के लिए यह करना है, क्योंकि उपयोगकर्ता स्वयं को सक्षम नहीं कर पाएगा।

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

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