समवर्ती शब्दकोश सही उपयोग


84

क्या मैं यह सोचने में सही हूं कि यह एक समवर्ती शब्दकोश का सही उपयोग है

private ConcurrentDictionary<int,long> myDic = new ConcurrentDictionary<int,long>();

//Main thread at program startup

for(int i = 0; i < 4; i++)
{
  myDic.Add(i, 0);
}

//Seperate threads use this to update a value

myDic[InputID] = newLongValue;

मेरे पास कोई ताले आदि नहीं हैं और मैं केवल शब्दकोश में मूल्य को अपडेट कर रहा हूं, भले ही कई धागे एक ही करने की कोशिश कर रहे हों।


2
यह निर्भर करता है - newLongValueके पिछले मूल्य पर निर्भर करता है myDic[InputID]?
डेमियन_इन_यूएनबेलिएवर

3
आपको myDic[InputID]दौड़ की स्थिति के लिए सीधे कुंजी तक पहुंचने से बचना चाहिए । आपको प्रयास करना चाहिएGetOrAdd
ओलिवियर अल्बर्टिनी

3
@OlivierAlbertini, मुझे नहीं लगता कि myDic[InputID]किसी भी समस्या का कारण बनता है जब इसका उपयोग एक लावेलु के रूप में किया जाता है। GetOrAddयह एक सही प्रतिस्थापन नहीं है क्योंकि यह केवल तभी जोड़ता है जब मूल्य मौजूद नहीं है। हम इसके बजाय AddOrUpdateशब्दकोश में समान मूल्य जोड़ने / अपडेट करने के लिए उपयोग कर सकते हैं ।
जतिन सांघवी

जवाबों:


75

यह इस बात पर निर्भर करता है कि थ्रेड-सेफ से आपका क्या मतलब है।

MSDN से - कैसे करें: एक समवर्ती छाया से आइटम जोड़ें और निकालें :

ConcurrentDictionary<TKey, TValue>मल्टीथ्रेडेड परिदृश्यों के लिए डिज़ाइन किया गया है। संग्रह से आइटम जोड़ने या निकालने के लिए आपको अपने कोड में ताले का उपयोग करने की आवश्यकता नहीं है। हालाँकि, एक थ्रेड के लिए एक मान प्राप्त करना हमेशा संभव होता है, और उसी थ्रेड को एक नया मान देकर संग्रह को तुरंत अपडेट करने के लिए एक और थ्रेड।

तो, शब्दकोश में किसी आइटम के मूल्य का असंगत दृश्य प्राप्त करना संभव है ।


2
एक दिलचस्प बात है! क्या आप अभी भी उस परिदृश्य में लॉक का उपयोग करेंगे?
जॉन

@ जौन - यह आपके आवेदन पर निर्भर करता है और यह ठीक है कि आप क्या करेंगे। लेकिन मैं कहूंगा कि यदि आप आइटमों के लगातार विचार चाहते हैं, तो आपको प्रत्येक आइटम को एक लॉक में पढ़ने और अपडेट करने की आवश्यकता होगी।
O

12
मुझे लगता है कि यह डॉक का कहना नहीं है। विसंगति का दृश्य के साथ क्या करना है, अगर दृश्य सिर्फ मूल्य है, तो यह पूरी तरह से सुसंगत है। जब तक आपको एक कुंजी का मूल्य मिलता है, तब तक शब्दकोश में कुंजी का मूल्य बदल सकता है। यह DateTime.Now मान के रूप में असंगत है।
जॉर्ज मावृतसकिस

4

इसका पता लगाने का सबसे अच्छा तरीका है MSDN प्रलेखन की जाँच करें।

समवर्ती के लिए पृष्ठ http://msdn.microsoft.com/en-us/library/dd287191.aspx है

थ्रेड सेफ्टी सेक्शन के तहत, यह कहा गया है कि "समवर्ती (TKey, TValue) के सभी सार्वजनिक और संरक्षित सदस्य थ्रेड-सुरक्षित हैं और इन्हें कई थ्रेड से समवर्ती रूप से उपयोग किया जा सकता है।"

इसलिए समसामयिक दृष्टिकोण से आप ठीक हैं।


2

हाँ आप सही है।

यह कि किसी एक धागे पर शब्दकोश को दूसरे धागे में बदलने की संभावना को उस वर्ग के लिए अस्तित्व का एकमात्र साधन है।


9
मुझे जो जोड़ना है, वह यह है कि यहाँ कैसे और कब उपयोग करना है, की उपयोगी जानकारी दी गई है ConcurrentDictionary
एलेक्स।

1

यह निर्भर करता है, मेरे मामले में मैं इस पद्धति का उपयोग करना पसंद करता हूं।

ConcurrentDictionary<TKey, TValue>.AddOrUpdate Method (TKey, Func<TKey, TValue>, Func<TKey, TValue, TValue>);

देखें MSDN लाइब्रेरी विधि उपयोग जानकारी के लिए।

नमूना उपयोग:

results.AddOrUpdate(
  Id,
  id => new DbResult() {
     Id = id,
     Value = row.Value,
     Rank = 1
  },
  (id, v) =>
  {
     v.Rank++;
     return v;
  });

2
FYI करें: "जब आप एक मान कारखाना विधि (GetOrAdd और AddOrUpdate विधियों के लिए) की आपूर्ति करते हैं, तो यह वास्तव में चल सकता है और बाद में इसका परिणाम समाप्त हो सकता है (क्योंकि कुछ अन्य धागे ने दौड़ जीती थी)।" अधिक जानकारी यहाँ: arbel.net/2013/02/03/…
keremispirli

हां, आप सही हैं, क्योंकि यह टिप्पणी अनुभाग में नोट किया गया है "यदि आप अलग-अलग थ्रेड्स पर AddOrUpdate को एक साथ कहते हैं, तो AddValueFactory को कई बार कहा जा सकता है, लेकिन इसकी कुंजी / मूल्य जोड़ी हर कॉल के साथ शब्दकोश में नहीं जोड़ी जा सकती है।" इसलिए आपको यह सुनिश्चित करने की आवश्यकता है कि आप कई लगातार वस्तुओं को उत्पन्न नहीं कर रहे हैं।
ओनूर

और अगर आपको सामग्री को अपडेट करने की आवश्यकता है, तो संग्रहीत ऑब्जेक्ट को पूरी तरह से बदलना नहीं है, उदाहरण के लिए पहले से जोड़े गए ऑब्जेक्ट की संपत्ति को बदलने के लिए, यह विधि उपयोगी है, अन्यथा आपको ताले या अन्य सिंक्रनाइज़ेशन विधियों का उपयोग करने की आवश्यकता है।
ओनूर

1

बस एक नोट: एक रेखीय लूप के साथ एक समवर्ती डोनोनेटरी ऑब्जेक्ट का उपयोग करने का औचित्य नहीं है , जिससे इसे कम कर दिया गया है। सबसे अच्छा विकल्प के रूप में से उल्लेख किया है, माइक्रोसॉफ्ट प्रलेखन की सिफारिशों का पालन करने के लिए है Oded समानता का उपयोग कर, नीचे दिए गए उदाहरण के अनुसार:

Parallel.For(0, 4, i => 
{
   myDic.TryAdd(i, 0);
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.