2017-01-05 8 views
6

मेरा प्रश्न थोड़ा सैद्धांतिक है कि मैं जानना चाहता हूं कि List<object> थ्रेड-सुरक्षित है अगर मैंने Parallel.For इस तरह से उपयोग किया था। कृपया नीचे देखें:सी # समांतर लूप स्थानीय चर धागा सुरक्षित जानकारी

public static List<uint> AllPrimesParallelAggregated(uint from, uint to) 
     { 
      List<uint> result = new List<uint>(); 
      Parallel.For((int)from, (int)to, 
       () => new List<uint>(), // Local state initializer 
       (i, pls, local) =>  // Loop body 
       { 
        if (IsPrime((uint)i)) 
        { 
         local.Add((uint)i); 
        } 
        return local; 
       }, 
       local =>    // Local to global state combiner 
       { 
        lock (result) 
        { 
         result.AddRange(local); 
        } 
       }); 
      return result; 
     } 

local सूची थ्रेड सुरक्षित है? क्या मेरे पास result सूची में सही डेटा है, बिना डेटा के बिना कई धागे के कारण डेटा बदल रहा है क्योंकि मेरे पास सामान्य लूप है?

नोट: मुझे सूची आदेश के बारे में चिंता नहीं है। मैं सूची और डेटा की लंबाई के बारे में जानना चाहता हूं।

+0

'सूची' समानांतर धागा सुरक्षित नहीं है, विशेष रूप से आप कैसे इरादा रखते हैं। –

+0

तो, इसका मतलब है कि मेरी 'परिणाम' सूची में वही डेटा नहीं होगा जैसा कि मैं सामान्य पाश से प्राप्त कर सकता हूं? – Saadi

+0

इसका मतलब है ..... 'सूची' धागा सुरक्षित नहीं है !! –

उत्तर

6

क्या यह समाधान थ्रेड-सुरक्षित है? तकनीकी रूप से हां, हकीकत में नहीं।

की बहुत धारणा एक धागा सुरक्षित List (के रूप में एक कतार या एक बैग के खिलाफ) उस सूची, आदेश, या, अधिक सख्ती से, सूचकांक के संबंध में सुरक्षित है के बाद से वहाँ कोई कुंजी है आरोही पूर्णांक के अलावा। समानांतर दुनिया में, जब आप इसके बारे में सोचते हैं, तो यह एक गैर-अवधारणात्मक अवधारणा है। यही कारण है कि System.Collections.Concurrent नामस्थान में ConcurrentBag और ConcurrentQueue है लेकिन ConcurrentList नहीं है।

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

यदि आप समानांतर गणना का उपयोग करना चाहते हैं, तो आपको अपने परिणामों को बैग में स्टोर करना होगा, फिर जब सभी धागे समाप्त हो जाएंगे तो क्रमबद्ध सूची उत्पन्न करने के लिए बैग को सॉर्ट करें। अन्यथा आपको श्रृंखला में गणना करना होगा।

और चूंकि आपको किसी भी बैग का उपयोग करना है, तो आप ConcurrentBag का भी उपयोग कर सकते हैं, और फिर आपको lock{} कथन से परेशान नहीं होना पड़ेगा।

+0

आपको अच्छा और संक्षिप्त उत्तर धन्यवाद ... – Saadi

+0

हाँ। यदि मैं इस तरह की चीज़ के लिए PLINQ पसंद नहीं करता तो एक 'ConcurrentBag' शायद मेरे समाधान में विशेषता होगी। – spender

2

List<T> थ्रेड-सुरक्षित नहीं है। जिस तरह से आप इसका उपयोग कर रहे हैं, थ्रेड सुरक्षा की आवश्यकता नहीं है। जब आप एकाधिक धागे से एक संसाधन का उपयोग करते हैं तो आपको थ्रेड सुरक्षा की आवश्यकता होती है। आप ऐसा नहीं कर रहे हैं, क्योंकि आप स्थानीय सूचियों पर काम कर रहे हैं।

अंत में आप स्थानीय सूचियों की सामग्री result चर में जोड़ रहे हैं। चूंकि आप इस ऑपरेशन के लिए lock का उपयोग करते हैं, इसलिए आप उस ब्लॉक के भीतर थ्रेड-सुरक्षित हैं।

तो आपका समाधान शायद ठीक है।

+0

आपको अच्छा और संक्षिप्त उत्तर धन्यवाद .. – Saadi

3

सूची थ्रेड सुरक्षित नहीं है। लेकिन आपका वर्तमान एल्गोरिदम काम करता है। क्योंकि यह अन्य उत्तर और टिप्पणियों में समझाया गया था।

यह प्रत्येक थ्रेड कि पाश को फांसी में भाग लेता है और उन धागों से प्रत्येक के लिए प्रारंभिक स्थानीय राज्य रिटर्न के लिए एक बार शुरू हो जाती है For.Parallel

<paramref name="localInit"/> प्रतिनिधि के localInit के बारे में वर्णन है। इन प्रारंभिक राज्यों पहले


को पास किया जाता IMO आप अपने पाश अंदर अनावश्यक जटिलता जोड़ रहे हैं। मैं इसके बजाय ConcurrentBag का उपयोग करूंगा। जो डिजाइन द्वारा धागा सुरक्षित है।

ConcurrentBag<uint> result = new ConcurrentBag<uint>(); 
Parallel.For((long) from, (long) to, 
    (i, PLS) => 
    { 
     if (IsPrime((uint)i)) 
     { 
      result.Add((uint)i); // this is thread safe. don't worry 
     } 
    }); 
return result.OrderBy(I => I).ToList(); // order if that matters 

See concurrent bag here

ConcurrentBag के सभी सार्वजनिक और संरक्षित सदस्यों धागा सुरक्षित हैं और एक से अधिक थ्रेड से समवर्ती इस्तेमाल किया जा सकता है।

+0

आपके उत्तर के लिए धन्यवाद लेकिन मेरा सवाल यह है कि हर कोई कह रहा है कि सूची थ्रेड सुरक्षित नहीं है। आप कैसे कह सकते हैं कि 'परिणाम। जोड़ें ((uint) i);' धागा सुरक्षित है? – Saadi

+0

यह ConcurrentBag है। एक सूची नहीं ConcurrentBag इस उद्देश्य के लिए बनाया गया है। –

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