2010-06-21 9 views
5

मेरा मानना ​​है कि यह काम करता है, मैं (हालांकि दौड़ की स्थिति और गतिरोध के लिए नहीं विस्तृत रूप से) एकाधिक समवर्ती धागे के साथ जाँच की है:सी # .NET 4.0 ConcurrentDictionary: एक लॉक के भीतर कोशिश करें?

public static System.Collections.Concurrent.ConcurrentDictionary<string, item> dict = 
     new System.Collections.Concurrent.ConcurrentDictionary<string, item>(); 
public static item dump; 

...

foreach (System.Collections.Generic.KeyValuePair<string, item> x in dict) 
{ 
    lock (x.Value) 
    { 
     if (x.Value.IsCompleted) 
     { 
      dict.TryRemove(x.Key, out dump); 
     } 
    } 
} 

यह सवाल एक की तरह है इस सवाल की निरंतरता:

Can I remove items from a ConcurrentDictionary from within an enumeration loop of that dictionary?

और इस सवाल:

Updating fields of values in a ConcurrentDictionary

कि मैं दो "dicey" युद्धाभ्यास कर रहा हूँ: एक ConcurrentDictionary से

  1. निकाला जा रहा है मानों एक ही समय में यह माध्यम से गणना (जो ठीक हो रहा है)।
  2. के Value भाग को लॉक करना। आवश्यक है क्योंकि मान के फ़ील्ड में हेरफेर करना थ्रेड सुरक्षित नहीं है, केवल ConcurrentDictionary के मूल्यों को मैन्युअल रूप से जोड़ना थ्रेड सुरक्षित है (ऊपर दिया गया कोड एक बड़े कोड ब्लॉक का एक स्निपेट है जिसमें मूल्यों के क्षेत्र वास्तव में छेड़छाड़ किए जाते हैं)।

उत्तर

4

एक समवर्ती शब्दकोश से मूल्यों को हटाने के दौरान इसे ठीक करने के दौरान ठीक है। इसमें कुछ प्रदर्शन प्रभाव हो सकते हैं (मुझे यकीन नहीं है) लेकिन इसे काम करना चाहिए।

ध्यान दें कि आप ConcurrentDictionary पर कुछ आंतरिक पर लॉक नहीं कर रहे हैं - आप item ऑब्जेक्ट से जुड़े मॉनीटर पर लॉक कर रहे हैं। मैं व्यक्तिगत रूप से ऐसा नहीं करना चाहता हूं: या तो इन वस्तुओं को थ्रेड-सुरक्षित होना चाहिए (इसे वैसे भी छेड़छाड़ करना ठीक है) या (अधिमानतः) अपरिवर्तनीय है ताकि आप लॉक किए बिना किसी भी धागे से उन्हें देख सकें। या आप केवल उस व्यक्तिगत संपत्ति को बना सकते हैं जिसे आप थ्रेड-सुरक्षित जांच रहे हैं। दस्तावेज़ जो भी आप करते हैं!

अंत में, out dump का उपयोग थोड़ा संदिग्ध लगता है। क्या पॉइंट सिर्फ TryRemove देने के लिए कुछ है? यदि ऐसा है, तो मैं एक स्थिर चर के बजाय स्थानीय चर का उपयोग करता हूं।

+1

धन्यवाद जॉन हाँ: डंप एक व्यर्थ मोहक करने के लिए है।मैं इसे एक स्थानीय चर में बदल दूंगा, क्योंकि एक वैश्विक दायरा सार्वजनिक स्थैतिक एक भेद्यता आइटम के भीतर गुण है: जैसा कि आप सुझाव देते हैं, मैं आइटम के बजाय व्यक्तिगत गुणों को लॉक कर दूंगा। इसे संभालने के लिए एक और शानदार तरीका हो सकता है, लेकिन इन गुणों को एक थ्रेड में बदल दिया जाएगा, दूसरे में पढ़ा जाएगा, और तीसरे चीयर्स में आइटम स्तर पर हटा दिया जाएगा! – circletimessquare

0

एक शानदार विकल्प जो मैंने हाल ही में पाया है, वह केवल कुंजी/मूल्य मिलान है, जिसका मतलब है कि आप एक ऑब्जेक्ट को हटाने की गारंटी दे सकते हैं (बेहतर मूल्य प्रकार, संदर्भ प्रकार नहीं) कि वहां कोई नहीं था परिवर्तन। उदाहरण:

ConcurrentDictionary<string, int> cc = new ConcurrentDictionary<string, int>(); 

     cc.GetOrAdd("1", 1); 

अब मान लीजिए कि नीचे दी गई दो पंक्तियां एक समवर्ती/बहुप्रचारित परिदृश्य में चल रही हैं।

 cc.AddOrUpdate("1", 2, (a,b) => b + 1); 

     var removeSuccess = ((ICollection<KeyValuePair<string, int>>)cc).Remove(
    new KeyValuePair<string, int>("1", 1)); 

मूल्य परिवर्तन नहीं होता है, तो आप निकाल देंगे "1" सफलतापूर्वक के साथ, अन्यथा क्योंकि आप पहले से ही कुंजी के लिए एक नया मूल्य असफल हो जायेगी।

नीचे अधिक जानकारी की जांच के लिए: http://thargy.com/2012/09/the-hidden-secret-of-the-concurrent-dictionary/ या http://blogs.msdn.com/b/pfxteam/archive/2011/04/02/10149222.aspx