एक असुरक्षित वेतन वृद्धि/कमी धागा सुरक्षित नहीं है - और इस तरह परमाणु नहीं धागे के बीच। (हालांकि यह "परमाणु" हो सकता है WRT वास्तविक आईएल/एमएल बदलना।)
यह LINQPad उदाहरण कोड अप्रत्याशित परिणाम दिखाता है:
void Main()
{
int nWorkers = 10;
int nLoad = 200000;
int counter = nWorkers * nLoad;
List<Thread> threads = new List<Thread>();
for (var i = 0; i < nWorkers; i++) {
var th = new Thread((_) => {
for (var j = 0; j < nLoad; j++) {
counter--; // bad
}
});
th.Start();
threads.Add(th);
}
foreach (var w in threads) {
w.Join();
}
counter.Dump();
}
ध्यान दें कि धागे के बीच दृश्यता महत्व की है । सिंक्रनाइज़ेशन परमाणुता के अलावा इस दृश्यता की गारंटी देता है।
यह कोड कम से कम सीमित संदर्भ में प्रस्तुत किया गया है, आसानी से तय किया गया है।घटती बाहर स्विच और परिणामों पर नज़र डालें: यहां तक कि जब एक volatile
चर का उपयोग कर
counter--; // bad
Interlocked.Decrement(ref counter); // good
lock (threads) { counter--; } // good
, परिणाम अभी भी अप्रत्याशित हैं। ऐसा लगता है कि (कम से कम यहां, जब मैंने इसे अभी चलाया) यह भी एक परमाणु ऑपरेटर के रूप में प्रतिस्पर्धी धागे के पढ़ने/ओप/लिखने के रूप में interleaved थे। उस व्यवहार अभी भी गलत जब दृश्यता मुद्दों हटा दिया जाता है यह देखने के लिए (वे कर रहे हैं?),
class x {
public static volatile int counter;
}
जोड़ सकते हैं और स्थानीय counter
चर के बजाय x.counter
उपयोग करने के लिए उपरोक्त कोड संशोधित।
बेहतर सवाल यह है कि * * idleAgents' concurrency सुरक्षित * का उपयोग करता है? – user2246674
संभावित डुप्लिकेट [क्या ++ ऑपरेटर थ्रेड सुरक्षित है?] (Http://stackoverflow.com/questions/4628243/is-the-operator-thread-safe) – nawfal