2009-09-22 17 views
42

विशेषसी # सरणी धागे सुरक्षित हैं?

  1. में एक सरणी और पैरामीटर के रूप में एक सूचकांक लेने के लिए एक समारोह बनाएँ।
  2. एक एन तत्व सरणी बनाएँ।
  3. एन गिनती लूप बनाएं।
  4. एक नया धागा पर पाश अंदर सरणी इंडेक्सर में पारित का उपयोग करने वस्तु का एक नया उदाहरण आवंटित।

मैं कैसे धागे का प्रबंधन करने आदि मैं पता है कि में दिलचस्पी है, तो इस सूत्र है कुछ करने का सुरक्षित तरीका।

class Program 
{ 
    // bogus object 
    class SomeObject 
    { 
     private int value1; 
     private int value2; 

     public SomeObject(int value1, int value2) 
     { 
      this.value1 = value1; 
      this.value2 = value2; 
     } 
    } 

    static void Main(string[] args) 
    { 

     var s = new SomeObject[10]; 
     var threads = Environment.ProcessorCount - 1; 
     var stp = new SmartThreadPool(1000, threads, threads); 
     for (var i = 0; i < 10; i++) 
     { 
      stp.QueueWorkItem(CreateElement, s, i); 
     } 

    } 

    static void CreateElement(SomeObject[] s, int index) 
    { 
     s[index] = new SomeObject(index, 2); 
    } 
} 
+20

यह पूरी तरह से सवाल के बिंदु पर नहीं है, लेकिन मैं 'पर्यावरण। प्रोसेसर काउंटर - 1' का उपयोग करने के खिलाफ सलाह दूंगा - उन गरीब सिंगल कोर लोगों को अन्यथा नाखुश हो जाएगा ... –

+6

ऐसे लोग हैं जो सिंगल- कोर प्रोसेसर? – Gary

+4

@ गैरी "एक" प्रोसेसर के साथ वर्चुअल मशीनें हैं;) – IamIC

उत्तर

39

मेरा मानना ​​है कि यदि प्रत्येक धागा केवल सरणी के एक अलग हिस्से पर काम करता है, तो सब ठीक रहेगा। यदि आप पर डेटा (i। ई। थ्रेड के बीच संवाद) पर जा रहे हैं तो आपको मेमोरी मॉडल के मुद्दों से बचने के लिए कुछ प्रकार की मेमोरी बाधा की आवश्यकता होगी।

मैं का मानना ​​है कि यदि आप धागे का एक समूह, जिनमें से प्रत्येक सरणी के अपने स्वयं के अनुभाग भरता अंडे, तो Thread.Join का उपयोग कर समाप्त करने के लिए उन लोगों के धागे के सभी के लिए प्रतीक्षा करें, कि उस के लिए बाधाओं के मामले में पर्याप्त करना होगा आप सुरक्षित रहना इस समय इसके लिए मेरे पास कोई सहायक दस्तावेज नहीं है, आपको दिमाग ...

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

+3

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

+0

@ स्टेवेन: हाँ, यह मेरी समझ के बारे में था :) –

+2

@ स्टेवेन "क्या यह सुरक्षित है कि कोडर क्या कर रहा है, इस पर निर्भर करता है।" - क्या यह कहने जैसा नहीं है "नहीं, यह सुरक्षित नहीं है।" ? – Rik

24

MSDN documentation on Arrays का कहना है:

लोक स्थिर (विजुअल बेसिक में साझा) इस प्रकार के सदस्यों धागा सुरक्षित हैं। कोई भी इंस्टेंस सदस्य नहीं है जो थ्रेड सुरक्षित होने की गारंटी देता है।

यह कार्यान्वयन एरे के लिए सिंक्रनाइज़ (थ्रेड सुरक्षित) रैपर प्रदान नहीं करता है; हालांकि, एआरई के आधार पर .NET Framework कक्षाएं सिंक्रूट संपत्ति का उपयोग कर संग्रह का स्वयं सिंक्रनाइज़ संस्करण प्रदान करती हैं।

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

तो नहीं, वे थ्रेड सुरक्षित नहीं हैं।

+13

यह मेरे प्रश्न का उत्तर नहीं देता है। मैं कोई गणना नहीं कर रहा हूं कि इस आदमी को 13 वोट कैसे मिल सकते हैं? – Gary

+4

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

+6

यह उत्तर वास्तव में अनुपयोगी है, क्योंकि एमएसडीएन उद्धरण काफी भ्रामक है * और * बिंदु पर नहीं। संदर्भ प्रकारों के लिए ऐरे पहुंच परमाणु हैं; यहां तक ​​कि इस तरह की एक सरणी (हालांकि संभवतः मूर्खतापूर्ण) पर भी गणना करना उस डिग्री थ्रेड-सुरक्षित है। –

11

आम तौर पर जब संग्रह को 'थ्रेडसेफ नहीं कहा जाता है' का अर्थ है कि समवर्ती पहुंच आंतरिक रूप से विफल हो सकती है (उदाहरण के लिए सूची < टी> के पहले तत्व को पढ़ने के लिए सुरक्षित नहीं है जबकि एक और धागा अंत में एक तत्व जोड़ता है सूची: सूची < टी> अंतर्निहित सरणी का आकार बदल सकती है और डेटा की प्रतिलिपि बनाने से पहले पढ़ने की पहुंच नई सरणी पर जा सकती है)।

ऐसी त्रुटियां सरणी के साथ असंभव हैं क्योंकि सरणी निश्चित आकार हैं और उनमें कोई 'संरचना परिवर्तन नहीं है'। तीन तत्वों के साथ एक सरणी तीन चर से अधिक या कम थ्रेड-सुरक्षित नहीं है।

सी # विनिर्देश इस बारे में कुछ भी नहीं कहता है; लेकिन यह स्पष्ट है कि यदि आप आईएल जानते हैं और सीएलआई विनिर्देश पढ़ते हैं - तो आप एक प्रबंधित संदर्भ प्राप्त कर सकते हैं (जैसे सी # "रेफरी" पैरामीटर के लिए इस्तेमाल किए गए जैसे) एक सरणी के अंदर एक तत्व के लिए और फिर सामान्य और अस्थिर भार और स्टोर दोनों करते हैं। सीएलआई स्पेक ऐसे लोड और स्टोर्स के लिए थ्रेड-सुरक्षा गारंटी का वर्णन करता है (उदाहरण के लिए तत्व < = 32 बिट के लिए परमाणुता)

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

4

जो उदाहरण आप प्रदान कर रहे हैं वह माइक्रोसॉफ्ट के सी # 4.0 काम के समानांतर एक्सटेंशन के समान ही है।

पाश के लिए

यह:

for (int i = 0; i < 100; i++) { 
    a[i] = a[i]*a[i]; 
} 

हो जाता है

Parallel.For(0, 100, delegate(int i) { 
    a[i] = a[i]*a[i]; 
}); 

तो, हाँ, अपने उदाहरण ठीक होना चाहिए। सी # में नए समांतर समर्थन के बारे में यहां एक पुराना blog post है।

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