2010-08-29 20 views
29
class Unit { 
    private readonly string name; 
    private readonly double scale; 

    public Unit(string name, double scale) { 
     this.name = name; 
     this.scale = scale, 
    } 

    public string Name { get { return name; } } 
    public string Scale { get { return scale; } } 

    private static Unit gram = new Unit("Gram", 1.0); 

    public Unit Gram { get { return gram; } } 
} 

एकाधिक धागे के पास Unit.Gram तक पहुंच है। एकाधिक धागे के साथ-साथ Unit.Gram.Title पढ़ने के लिए यह ठीक क्यों है?अपरिवर्तनीय वस्तुएं थ्रेड-सुरक्षित क्यों हैं?

मेरी चिंता यह है कि वे एक ही स्मृति स्थान का जिक्र कर रहे हैं। एक धागा उस स्मृति को पढ़ना शुरू कर देता है, तो क्या यह "लॉक आउट" नहीं है? क्या इस महत्वपूर्ण खंड के लिए .NET हैंडल सिंक्रनाइज़ेशन है? या क्या मैं सोच रहा हूं कि एक साथ पढ़ने के लिए सिंक्रनाइज़ेशन की आवश्यकता है?

+0

"मेरी चिंता यह है कि वे एक ही स्मृति स्थान का जिक्र कर रहे हैं।" क्या वो? शायद। यह आपकी चिंता नहीं है, यह वीएम की चिंता है। एक साथ पढ़ने के लिए सिंक्रनाइज़ेशन की आवश्यकता नहीं है, यह क्यों होगा? –

+2

* "यह क्यों होगा" * >> क्या यह प्रश्न यहां नहीं है? अगर मैं वही पुस्तक पढ़ता हूं जो मेरी प्रेमिका पढ़ती है, उसी समय, हम हमेशा इसके बारे में लड़ते हैं। मुझे पता है कि यह कंप्यूटर में कोई समस्या नहीं है हालांकि (एक ही समय में पढ़ने वाले दो थ्रेड नहीं होते हैं, सीपीयू आर्किटेक्चर इसका ख्याल रखता है), लेकिन मुझे यह एक बहुत ही वैध सवाल मिल रहा है :) – Abel

+0

पुस्तक पढ़ने में एक परिवर्तनीय स्थिति शामिल है (वर्तमान पृष्ठ, बिजली, आदि)। आप पुस्तक पर लड़ नहीं रहे हैं, लेकिन इसकी प्रसंस्करण। – sisve

उत्तर

11

मुझे लगता है कि आपके सवाल का नहीं पता चला है धागे की सुरक्षा या के बारे में होने अपरिवर्तनीयता लेकिन स्मृति पहुंच के (बहुत) निम्न स्तर के विवरण के बारे में।

और यह एक भारी विषय है लेकिन संक्षिप्त उत्तर यह है: हां, दो धागे (और अधिक महत्वपूर्ण, 2+ सीपीयू) एक साथ स्मृति के एक ही टुकड़े को पढ़ सकते हैं (और/या लिख ​​सकते हैं)।

और जब तक कि स्मृति क्षेत्र की सामग्री अपरिवर्तनीय है, तब तक सभी समस्याएं हल हो जाती हैं। जब यह बदल सकता है, तो मुद्दों की एक पूरी श्रृंखला है, volatile कीवर्ड और Interlocked कक्षा कुछ ऐसे टूल हैं जिन्हें हम हल करने के लिए उपयोग करते हैं।

+1

निम्न स्तर पर, जैसा कि आप कहते हैं, मुझे विश्वास है कि स्मृति की एक साथ पहुंच नहीं होती है। प्रोसेसर एक ही समय में एक ही स्मृति तक नहीं पहुंच सकते हैं, जब तक कि उस स्मृति को कैश नहीं किया जाता है। अन्यथा, मेमोरी बस का उपयोग किया जाना चाहिए, जिसका उपयोग उस समय केवल एक प्रोसेसर द्वारा किया जा सकता है। यह प्रोसेसर स्टालों और प्रदर्शन लाभ को सीमित करता है एकाधिक प्रोसेसर दे सकता है (मेमोरी एक्सेस सीपीयू की तुलना में धीमी गति से कई गुना है)। एक उपाय [NUMA अवधारणा या वास्तुकला] (http://en.wikipedia.org/wiki/Non-Uniform_Memory_Access) है, जहां अलग-अलग बसों का उपयोग स्मृति स्थानों (अभी भी अलग) तक पहुंचने के लिए किया जाता है: – Abel

+0

@Abel, आप सही हैं लेकिन मैंने इसे 'छोटी कहानी' कहा: जहां तक ​​हम (प्रोग्रामर) बता सकते हैं, यह एक साथ है। असेंबली भाषा प्रोग्रामर के लिए भी। –

+0

मेरा मानना ​​है कि आप सही हैं। लेकिन स्मृति की रैमिकेशन सिंक्रनाइज़ेशन को पारदर्शी रूप से संभाला जा रहा है, वास्तव में, अपरिवर्तनीयता ergo थ्रेड-सुरक्षा है। वास्तविक उत्तर ऐसा लगता है क्योंकि ** ** इसे ** के नीचे संभाला जाता है, और यह पूछताछ करता है कि इसे संभाला गया है या नहीं, उसके बाद इतना बेवकूफ नहीं था। :) – randomguy

4

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

57

कोई ऑब्जेक्ट थ्रेड सुरक्षित नहीं करता है? यदि कोई थ्रेड इसे पढ़ रहा है तो उस ऑब्जेक्ट का मान/स्थिति बदल सकता है, तो ऑब्जेक्ट थ्रेड सुरक्षित नहीं है। यह आमतौर पर तब होता है जब कोई दूसरा धागा इस ऑब्जेक्ट के मान को बदलता है जबकि पहला धागा इसे पढ़ रहा है।

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

+15

आप यह जोड़ सकते हैं कि जब एक अपरिवर्तनीय वस्तु प्रारंभ की जाती है, तो यह स्थिति * बदलती है *, लेकिन सीएलआर गारंटी देता है कि यह प्रक्रिया थ्रेड-सुरक्षित होती है (यानी, यह संभव नहीं है कि अन्य थ्रेड पढ़ने की कोशिश करता है जबकि init-process नहीं है सीटीओआर याक्टर में समाप्त)। – Abel

+0

@Abel: मुझे लगता है कि आपकी टिप्पणी सही है, लेकिन क्या आप भाषा मानक का संदर्भ ला सकते हैं जो आपके दावे का समर्थन करता है?विशेष रूप से, ऑब्जेक्ट प्रकाशन के पीछे कन्स्ट्रक्टर में लिखने के लिए असंभव क्यों है? – Vlad

11

साथ-साथ पढ़ता है सिंक्रनाइज़ेशन की आवश्यकता नहीं है। चूंकि सिंक्रनाइज़ेशन केवल लेखकों (या पाठकों और कम से कम एक लेखक के लिए आवश्यक है), अपरिवर्तनीय वस्तुओं को सिंक्रनाइज़ेशन की आवश्यकता नहीं होती है, और थ्रेडसेफ के लिए होते हैं।

3

समवर्ती पढ़ना अधिकांश मामलों में सिंक्रनाइज़ेशन की आवश्यकता नहीं है (अपवाद स्मृति मेमोरी आईओ जैसी चीजें हैं जहां एक निश्चित पते से पढ़ने से साइड इफेक्ट्स हो सकते हैं)।

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

+2

निष्पक्ष होने के लिए, कुछ स्तर पर, हार्डवेयर को इन मुद्दों से निपटना होगा। लेकिन यह हार्डवेयर में किया गया है और .NET अनुप्रयोग लेखक के कुछ भी नहीं कहने के लिए ओएस को भी दिखाई नहीं दे रहा है। – siride

+0

@ साइराइड, मुझे वास्तव में लगता है कि मुझे आपकी टिप्पणी को जवाब के रूप में स्वीकार करना चाहिए क्योंकि यह वास्तव में प्रश्न का उत्तर देता है। ** सिंक्रनाइज़ेशन को नीचे नियंत्रित किया जाता है। ** इसके बाद अपरिवर्तनीयता IMHO को समझना आसान है। – randomguy

+1

@randomguy, ठीक है, _some_ हार्डवेयर को कुछ स्तरों पर इन मुद्दों से निपटना होगा, लेकिन यह कुछ स्तरों पर पहले स्थान पर भी आवश्यकताओं को प्रस्तुत करता है। यदि आप यह कहना चाहते हैं कि यह "नीचे दिए गए हैं" जो आपको कहना है, "कुछ कंप्यूटर डिज़ाइनों पर जहां समवर्ती पढ़ने से डिज़ाइन विकल्पों के कारण समस्याएं पैदा हो सकती हैं, इस पर प्रभावित होने वाले सॉफ़्टवेयर की संभावना विभिन्न तंत्रों के माध्यम से समाप्त हो जाती है, अन्य डिज़ाइन होते हैं समवर्ती पढ़ने से प्रभावित नहीं है, और अभी भी अन्य समवर्ती पढ़ना असंभव है। " –

1

Memory Management Units प्रोसेसर का हिस्सा हैं जो स्मृति को पढ़ने को संभालता है। यदि आपके पास एक से अधिक हैं, तो एक बार नीले चंद्रमा में से 2 एक ही दर्जन नैनो-सेकेंड में उसी स्मृति स्थान को पढ़ने का प्रयास कर सकते हैं, लेकिन कोई समस्या नहीं होती है क्योंकि उन्हें एक ही जवाब मिलता है।

1

उदाहरण के लिए ड्राइवरों के लिए मैप किए गए मेमोरी जैसे अपवादों के अलावा, दो धागे एक ही स्मृति पते को पढ़ने के लिए कोई समस्या नहीं है। एक समस्या उत्पन्न हो सकती है जब एक धागा कुछ लिखता है डेटा हालांकि। इस मामले में, उस वस्तु/डेटा को पढ़ने के लिए अन्य धागे को रोका जा सकता है।

लेकिन समस्या यह लेखन के समकालीनता के कारण नहीं है (सबसे कम इलेक्ट्रॉनिक स्तर पर वे वैसे भी एक के बाद एक घटित), समस्या नहीं बल्कि उस वस्तु/आंकड़ों का सेट उनके स्थिरता खो सकते है। आमतौर पर एक section critic का उपयोग कुछ कोड को अलग करने के लिए करता है जिसे अन्य धागे द्वारा एक साथ पढ़ा/लिखा नहीं जा सकता है।

कहना नेट पर कई उदाहरण हैं, लेकिन, निम्नलिखित पर विचार price के साथ एक वर्ग के लिए एक निजी सदस्य है, उत्पाद है, जो भी 2 तरीकों

है
public void setPrice(int value) { 
    price = value; 
    // -- point CRITIC -- 
    price += TAX; 
} 

public int getPrice() { 
    return price; 
} 

setPrice (v) का मूल्य सेट वी के लिए एक उत्पाद, और वैट के साथ इसे समायोजित करें (कार्यक्रम में value += TAX; price = value होना चाहिए लेकिन यह यहां बिंदु नहीं है :-)

यदि थ्रेड ए 100 की कीमत लिखता है, और टैक्स (निश्चित) 1 है, तो उत्पाद मूल्य अंततः 101 पर सेट किया जाए। लेकिन क्या होता है यदि थ्रेड बी getPrice() के माध्यम से कीमत को पढ़ता है, जबकि थ्रेड ए point CRITIC पर है? बी में लौटाई गई कीमत टैक्स से चूक जाएगी, और गलत होगी।

setPrice() एक महत्वपूर्ण खंड (lock) के भीतर होना चाहिए, कीमत की स्थापना के दौरान वस्तु के लिए किसी भी उपयोग रोकने के लिए

lock(this) 
    { 
     price = value; 
     price += TAX; 
    } 
2

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

+0

मुझे लगता है कि यह वास्तव में सवाल का जवाब भी देता है। क्या आप इस उत्तर का विस्तार करना चाहते हैं? – randomguy

+0

असल में, 2 सीपीयू पढ़ सकते हैं उसी घड़ी-टिक में एक ही पता (और विभिन्न मान देखें)। ऐसा इसलिए है क्योंकि वे प्रत्येक अपने कैश से पढ़ेंगे। –

+0

यह सही है, लेकिन प्रश्न और सरलीकरण के प्रयोजनों के लिए मुझे एक सीपीयू स्थिति माननी पड़ी। हालांकि, बहु-सीपीयू स्थिति में परिवर्तन करने वाला एकमात्र हिस्सा स्मृति कैशिंग की संभावना है, लेकिन मान अभी भी वही है। भले ही परिवर्तनीय ग्राम स्थिर घोषित किया गया हो, इसके लिए कोई "सेटटर" नहीं है और यह है एक बार 1.0 के मूल्य के लिए शुरू किया गया। इसलिए यह अपरिवर्तनीय है और किसी भी प्रोग्राम सिंक्रनाइज़ेशन की आवश्यकता नहीं है। – venky

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