2011-02-16 13 views
22

मैं सुरक्षित नीचे कोडसूची <T> धागा सुरक्षा

var processed = new List<Guid>(); 
Parallel.ForEach(items, item => 
{ 
    processed.Add(SomeProcessingFunc(item)); 
}); 

उपयोग कर रहा हूँ ऊपर कोड धागा है? क्या संसाधित सूची दूषित होने का मौका है? या मुझे जोड़ने से पहले लॉक का उपयोग करना चाहिए?

var processed = new List<Guid>(); 
Parallel.ForEach(items, item => 
{ 
    lock(items.SyncRoot) 
     processed.Add(SomeProcessingFunc(item)); 
}); 

धन्यवाद।

+0

की ConcurrentBag आप MSDN पर देखने गए थे? यहां: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx#c9721fa0-1cd9-4a21-818c-98d164c9fc14 –

+1

देखें http://stackoverflow.com/questions/4779165/parallel-foreach-loop -odd-व्यवहार। – mellamokb

+0

@ मार्टिन्हो: हाँ। मैंने पढ़ा है कि सूची धागा सुरक्षित नहीं है। लेकिन मैं यह समझने में असमर्थ हूं कि सूची में एकाधिक धागे जोड़ रहे हैं, भले ही वह सूची को दूषित कैसे कर सके। – stackoverflowuser

उत्तर

23

नहीं! यह बिल्कुल सुरक्षित नहीं है, क्योंकि processed.Add नहीं है। आप निम्न कार्य कर सकते हैं:

items.AsParallel().Select(item => SomeProcessingFunc(item)).ToList(); 

ध्यान रखें कि Parallel.ForEach अनुक्रम के प्रत्येक तत्व के लिए जरूरी कार्यों के लिए ज्यादातर बनाया गया था। आप क्या करते हैं मानचित्र है: अनुक्रम के प्रत्येक मान को प्रोजेक्ट करें। Select के लिए बनाया गया था। AsParallel इसे सबसे कुशल तरीके से धागे में फैलाता है।

इस कोड को सही ढंग से काम करता है:

var processed = new List<Guid>(); 
Parallel.ForEach(items, item => 
{ 
    lock(items.SyncRoot) 
     processed.Add(SomeProcessingFunc(item)); 
}); 

लेकिन बहु सूत्रण के मामले में कोई मतलब नहीं है। प्रत्येक पुनरावृत्ति बल पर lock आईएनजी पूरी तरह अनुक्रमिक निष्पादन बलों, धागे का गुच्छा एकल धागे के लिए इंतजार कर रहा है।

+0

पूरा होने के लिए क्यों: अंत में http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx देखें, इसके पास थ्रेड सुरक्षा – rene

+0

@rene पर एक विषय है: tack '# c9721fa0-1cd9-4a21-818c -98d164c9fc14' उस पते के अंत तक और यह सीधे संबंधित खंड को इंगित करता है;) –

+0

उत्तर के लिए धन्यवाद। क्या यहां बताया गया है कि ConcurrentBag का उपयोग करना बेहतर होगा http://stackoverflow.com/questions/4779165/parallel-foreach-loop-odd-behavior – stackoverflowuser

4

Jon Skeet से शब्दों में इससे पहले कि वह यहाँ हो जाता है:

नेट 4 में Parellel एक्सटेंशन के हिस्से के रूप में, वहाँ कई नए संग्रह एक नया System.Collections.Concurrent नाम स्थान में हैं। अपेक्षाकृत कम लॉकिंग के साथ, समवर्ती एकाधिक थ्रेड से संचालन के चेहरे में सुरक्षित होने के लिए डिज़ाइन किया गया है।

इनमें IProducerConsumerCollection<T>, BlockingCollection<T>, ConcurrentBag<T>, ConcurrentQueue<T>, ConcurrentStack<T>, and ConcurrentDictionary<TKey, TValue> शामिल हैं।

+0

सहमत हुए। मेरा उत्तर देखें, जो System.Collections.Concurrent नेमस्पेस से एक प्रकार का उपयोग करता है। – mellamokb

0

पढ़ना धागा सुरक्षित है, लेकिन जोड़ना नहीं है। आपको एक पाठक/लेखक लॉक सेटअप की आवश्यकता है क्योंकि जोड़ने से आंतरिक सरणी का आकार बदल सकता है जो एक समवर्ती पढ़ने को गड़बड़ कर देगा।

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

लेकिन वास्तव में, एक सूची एक सरणी के लिए एक इंटरफ़ेस है।

0

एंड्री की answer के रूप में विकल्प:

items.AsParallel().Select(item => SomeProcessingFunc(item)).ToList(); 

तुम भी लिख सकता है

items.AsParallel().ForAll(item => SomeProcessingFunc(item)); 

इस क्वेरी इसके पीछे यह है कि और अधिक कुशल क्योंकि कोई मर्ज की आवश्यकता है, MSDN बनाता है। सुनिश्चित करें कि SomeProcessingFunc फ़ंक्शन थ्रेड-सुरक्षित है। और मुझे लगता है, लेकिन इसका परीक्षण नहीं किया गया है, अगर आपको किसी अन्य धागे (जोड़ना या निकालना) तत्वों में संशोधित किया जा सकता है, तो आपको अभी भी लॉक की आवश्यकता है।

1

का उपयोग प्रकार कुछ

var bag = new ConcurrentBag<List<Something>>; 
var items = GetAllItemsINeed(); 
Parallel.For(items,i =>       
    { 
     bag.Add(i.DoSomethingInEachI()); 
    }); 
संबंधित मुद्दे