2012-03-24 15 views
114

क्या कोई विधि थ्रेड-सुरक्षित बनाने के लिए कुल नियम/दिशानिर्देश हैं? मैं समझता हूं कि शायद एक मिलियन एक-ऑफ स्थितियां हैं, लेकिन सामान्य रूप से क्या? क्या यह आसान है?क्या विधि थ्रेड-सुरक्षित बनाता है? नियम क्या हैं?

  1. यदि कोई विधि केवल स्थानीय चर का उपयोग करती है, तो यह थ्रेड सुरक्षित है।

क्या यह है? क्या यह स्थैतिक तरीकों के लिए भी लागू होता है?

एक जवाब है, @Cybis द्वारा प्रदान की, था: क्योंकि प्रत्येक धागा अपनी ही ढेर हो जाता है

स्थानीय चर धागे के बीच साझा नहीं किया जा सकता।

क्या यह स्थिर तरीकों के मामले भी है?

यदि कोई विधि किसी संदर्भ वस्तु को पारित कर दी जाती है, तो क्या यह थ्रेड सुरक्षा को तोड़ देता है? मैंने कुछ शोध किया है, और कुछ मामलों के बारे में बहुत कुछ है, लेकिन मैं कुछ नियमों का उपयोग करके परिभाषित करने में सक्षम होने की उम्मीद कर रहा था, यह सुनिश्चित करने के लिए दिशानिर्देशों का पालन करना है कि कोई विधि थ्रेड सुरक्षित है।

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

संपादित
अच्छा अंक का एक बहुत यहाँ किया गया है। मुझे लगता है कि इस सवाल का वास्तविक जवाब यह है: "थ्रेड सुरक्षा सुनिश्चित करने के लिए कोई आसान नियम नहीं हैं।" ठंडा। ठीक। लेकिन सामान्य में मुझे लगता है कि स्वीकृत उत्तर एक अच्छा, संक्षिप्त सारांश प्रदान करता है। हमेशा अपवाद होते हैं। ऐसा ही होगा। में इसके साथ जी सकता हूँ।

+44

आप उन चरों तक नहीं पहुंच पाएंगे जो बिना किसी लॉक के अन्य धागे तक पहुंच सकते हैं। –

+3

हंथ पाथेंट एक ताकतवर हो गया है! –

+3

इसके अलावा .. 'वे उन चरों तक नहीं पहुंच पाएंगे जो लॉकथ के बिना अन्य थ्रेडों तक भी पहुंच सकते हैं' - अगर यह पढ़ा जाता है तो मूल्य उतना ही महत्वपूर्ण है जितना कि मूल्य पढ़ा जाता है, वह नवीनतम नहीं है या वास्तव में गलत है। –

उत्तर

99

एक विधि (उदाहरण या स्थिर) केवल उस विधि के भीतर scoped चर का संदर्भ है तो यह सुरक्षित थ्रेड क्योंकि प्रत्येक धागा अपने स्वयं के ढेर है:

इस उदाहरण में, एक से अधिक थ्रेड मुद्दा बिना समवर्ती ThreadSafeMethod कह सकते हैं। एक विधि किसी भी (वस्तु राज्य) तक पहुँचता है, तो गुण या क्षेत्रों (उदाहरण या स्थिर) तो

public class Thing 
{ 
    public int ThreadSafeMethod(string parameter1) 
    { 
     int number; 
     number = this.GetLength(parameter1); 
     return number; 
    } 

    private int GetLength(string value) 
    { 
     int length = value.Length; 
     return length; 
    } 
} 

:

public class Thing 
{ 
    public int ThreadSafeMethod(string parameter1) 
    { 
     int number; // each thread will have its own variable for number. 
     number = parameter1.Length; 
     return number; 
    } 
} 

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

public class Thing 
{ 
    private string someValue; // all threads will read and write to this same field value 

    public int NonThreadSafeMethod(string parameter1) 
    { 
     this.someValue = parameter1; 

     int number; 

     // Since access to someValue is not synchronised by the class, a separate thread 
     // could have changed its value between this thread setting its value at the start 
     // of the method and this line reading its value. 
     number = this.someValue.Length; 
     return number; 
    } 
} 

आपको लगता है कि जो एक struct या तो या अपरिवर्तनीय नहीं हैं विधि के लिए में पारित कोई पैरामीटर विधि के दायरे से बाहर एक और धागा द्वारा उत्परिवर्तित किया जा सकता है के बारे में पता होना चाहिए।

उचित सहमति सुनिश्चित करने के लिए आपको लॉकिंग का उपयोग करने की आवश्यकता है।

अधिक जानकारी के लिए lock statement C# reference और ReadWriterLockSlim देखें।

ताला ज्यादातर एक समय कार्यक्षमता में एक,
ReadWriterLockSlim यदि आप कई पाठकों और एकल लेखकों की जरूरत है उपयोगी है प्रदान करने के लिए उपयोगी है।

+9

तीसरे उदाहरण में 'निजी स्ट्रिंग कुछ वैल्यू;' 'स्थिर 'नहीं है इसलिए प्रत्येक इंस्टेंस को उस चर की एक अलग प्रति प्राप्त होगी। तो क्या आप कृपया बता सकते हैं कि यह थ्रेड सुरक्षित नहीं है? – Bharadwaj

+16

@ भारद्वाज यदि 'थिंग' वर्ग का एक उदाहरण है जो कई धागे –

+0

द्वारा एक्सेस किया गया है तो मैंने उस स्थिति को नहीं सोचा था! जवाब देने के लिए धन्यवाद :) – Bharadwaj

9

कोई कड़ी मेहनत और तेजी नियम नहीं है।

यहाँ कोड धागा .NET में सुरक्षित बनाने के लिए कुछ नियम हैं और क्यों इन अच्छा नियम नहीं हैं:

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

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

+8

ताले धीमी नहीं होने की जरूरत है। ताले अविश्वसनीय रूप से तेज़ हैं; एक uncontested ताला दस से सौ ** नैनोसेकंड ** की परिमाण के क्रम में है। प्रतियोगिता वाले ताले मनमाने ढंग से धीमे होते हैं; यदि आप धीमे हो गए हैं क्योंकि आप ताले का चुनाव कर रहे हैं तो * विवाद को हटाने के लिए प्रोग्राम को फिर से शुरू करें *। –

+2

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

92

यदि कोई विधि केवल स्थानीय चरों तक पहुंचती है, तो यह थ्रेड सुरक्षित है। क्या यही है?

बिल्कुल नहीं। आप केवल एक ही स्थानीय एकल थ्रेड से पहुँचा चर के साथ एक कार्यक्रम में लिख सकते हैं कि फिर भी threadsafe नहीं है:

https://stackoverflow.com/a/8883117/88656

करता है कि स्थिर तरीकों के लिए भी लागू होता है?

बिलकुल नहीं।

@Cybis द्वारा प्रदान किया गया एक उत्तर था: "स्थानीय चर को धागे के बीच साझा नहीं किया जा सकता है क्योंकि प्रत्येक थ्रेड को अपना स्वयं का ढेर मिलता है।"

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

क्या यह स्थिर तरीकों के मामले भी है?

बिलकुल नहीं।

यदि कोई विधि संदर्भ वस्तु पारित की जाती है, तो क्या यह थ्रेड सुरक्षा टूट जाती है?

शायद।

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

आपको निराशा से जीना सीखना होगा। यह एक बहुत मुश्किल विषय है।

तो, मुझे लगता है कि मेरी अंतिम सवाल यह है:?। "वहाँ नियम है कि एक धागा सुरक्षित विधि को परिभाषित की एक छोटी सूची है

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

इसके अलावा, तथ्य यह है कि आप सवाल पूछ रहे हैं कि थ्रेड सुरक्षा के बारे में आपकी मौलिक गलतफहमी को इंगित करता है। थ्रेड सुरक्षा वैश्विक है, एक प्रोग्राम की स्थानीय संपत्ति नहीं है। सही होने के लिए यह इतना कठिन क्यों है क्योंकि इसकी सुरक्षा सुनिश्चित करने के लिए आपको पूरे कार्यक्रम के थ्रेडिंग व्यवहार का पूरा ज्ञान होना चाहिए।

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

+0

आपने कहा: "आप हर विधि को नहीं देख सकते हैं और इसे 'सुरक्षित' के रूप में देख सकते हैं और फिर उम्मीद कर सकते हैं कि पूरा कार्यक्रम सुरक्षित है। " माना। लेकिन वास्तव में यह नहीं है कि मैं क्या पूछ रहा हूं। मैं कम से कम यह समझने की उम्मीद कर रहा हूं कि, हाँ, यह विधि चीजों को सही ढंग से कर रही है जहां तक ​​थ्रेड-सुरक्षा जाती है। निश्चित रूप से, कुछ * अन्य * विधि चीजों को थ्रेड-असुरक्षित बना सकती है, लेकिन कम से कम विधि ए उस परिप्रेक्ष्य से अच्छा दिखता है। –

+0

वैसे, मैं आपके उत्तर की सराहना करता हूं। जब मैं समय लेता हूं तो मैं आज बाद में इसका अध्ययन करूंगा। –

+7

कोर कथन: _Thread सुरक्षा एक वैश्विक है, न कि किसी प्रोग्राम की स्थानीय संपत्ति ._ –

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