2009-03-24 19 views
7

मैं बहुत की तरह एक स्थानीय चर है:थ्रेड सुरक्षा और स्थानीय चर

Increment() 
{ 
    int i = getFromDb(); // get count for a customer from db 
}; 

और यह एक उदाहरण वर्ग जो वृद्धि हो जाता है (जब भी कोई ग्राहक - एक उदाहरण वस्तु - कोई खरीदारी करता है), यह है परिवर्तनीय धागा सुरक्षित? मैंने सुना है कि स्थानीय चर धागे सुरक्षित हैं क्योंकि प्रत्येक धागे का अपना ढेर इत्यादि हो जाता है।

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

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

संपादित 2: इसके अलावा, getFromDb की थ्रेड सुरक्षा की गारंटी है क्योंकि यह केवल पढ़ने के संचालन करता है।

उत्तर

33

i एक स्थानीय (विधि) चर के रूप में घोषित किया जाता है, तो यह केवल सामान्य रूप सेIncrement() के ढेर फ्रेम में मौजूद है - तो हाँ, i धागा सुरक्षित है ... (हालांकि मैं टिप्पणी नहीं कर सकता getFromDb पर)।

को छोड़कर यदि:

  • Increment पुनरावर्तक ब्लॉक है (यानी yield return का उपयोग करता है या yield break)
  • i एक गुमनाम विधि (delegate { i = i + 1;}) या लैम्ब्डा (foo => {i=i+foo;}

में प्रयोग किया जाता है उपर्युक्त दो परिदृश्यों में, कुछ मामले हैं जब इसे ढेर के बाहर उजागर किया जा सकता है। लेकिन मुझे संदेह है कहां कर रहे हैं।

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

+0

पूर्णता के लिए +1 (एनन विधियों और इटरेटर ब्लॉक की चर्चा। स्टेटिक कक्षाएं और थ्रेड सुरक्षा व्यक्तिगत रूप से समझने की सबसे आसान अवधारणा है। :) – dotnetdev

+0

आईएमएचओ, यह स्पष्ट करना महत्वपूर्ण है कि सूचीबद्ध अपवादों में भी, स्थानीय चर विधि के लिए प्रत्येक कॉल के लिए _still_ अद्वितीय है। यही है, जबकि उन्हें विधि के संदर्भ में भी पहुंचा जा सकता है, यहां तक ​​कि संभावित रूप से गैर-थ्रेड-सुरक्षित तरीके से भी, वे _dif_ स्थानीय चर के सापेक्ष थ्रेड-सुरक्षित होंगे, उसी विधि में _different_ कॉल के संदर्भ में । –

5

आपके कथन में दो अलग-अलग हिस्से हैं - एक फ़ंक्शन कॉल, और एक असाइनमेंट।

असाइनमेंट थ्रेड सुरक्षित है, क्योंकि चर स्थानीय है। इस विधि के प्रत्येक अलग-अलग आमंत्रण को स्थानीय चर का अपना संस्करण प्राप्त होगा, प्रत्येक स्मृति में एक अलग स्थान पर एक अलग स्टैक फ्रेम में संग्रहीत होगा।

प्राप्त करने के लिए कॉल FROMDb() थ्रेडसेफ हो सकता है या नहीं हो सकता है - इसके कार्यान्वयन के आधार पर।

2

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

class Example 
{ 
    static int var1; //not thread-safe 

    public void Method1() 
    { int var2; //thread-safe 
    } 
} 
1

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

संगामिति और multithreading के साथ हमेशा की तरह, आप अपने डीबी पर सिंक्रनाइज़ करने के लिए अगर आप केवल जानकारी को पढ़ने की जरूरत नहीं है। जैसे ही दो धागे आपके डीबी से सूचनाओं के एक ही सेट को पढ़ने/लिखने की कोशिश करेंगे, आपको सिंक्रनाइज़ करने की आवश्यकता होगी।

1

मैं हो जाएगा "धागा सुरक्षित" प्रत्येक थ्रेड के रूप में यह स्टैक पर मैं की स्वयं की प्रतिलिपि है आप का सुझाव के रूप में होगा। असली सवाल GetFromDb() थ्रेड सुरक्षित की सामग्री होगी?

1

मैं एक स्थानीय चर तो यह राज्य साझा नहीं किया है।

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

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

1

मैं धागा सुरक्षित रूप से सुरक्षित है। लेकिन जब आप इंस्टेंस वैरिएबल के मान आवंटित करते हैं, उदाहरण के लिए विधि विधि वापसी मान, तो साझा डेटा एकाधिक धागे द्वारा छेड़छाड़ की जाती है।

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