दिलचस्प पोस्ट
मैं स्टैकट्र्रेस या प्रतिबिंब का उपयोग करके किसी विधि का कॉलर कैसे प्राप्त करूं? PHP खुले टैग "<? =" और "<? Php" / "<?" के बीच अंतर क्या है? JavaFX बीन्स बाइंडिंग अचानक काम करना बंद हो जाता है क्यों सी compilers बाह्य नामों को रेखांकित करते हैं? स्कैनर NoSuchElementException एंड्रॉइड ऐप में डेटा को कैसे बचाया जाए जावास्क्रिप्ट एरे ब्रेसिज़ बनाम ब्रैकेट्स CoreData संबंध गलती? अंगुल्य 2 राउटर.नैविगेट ताज़ा पेज जावा में नंबर के लिए अग्रणी शून्य जोड़ें? IPhone में पुनः अभिविन्यास के बाद "गलत" फ्रेम / विंडो आकार एंड्रॉइड: टुकड़े बैकस्टैक्स सीएसएस जस्टिफ़ टेक्स्ट, बिन्दुओं के साथ अंतरिक्ष भरें सी # का उपयोग कर एक .gz फाइल को अनज़िप करना मैं निकटतम एक्स मिनट में समय कैसे बढ़ा सकता हूं?

सी # यादृच्छिक संख्या जेनरेटर थ्रेड सुरक्षित है?

है सी # ' Random.Next() विधि धागा सुरक्षित है?

वेब के समाधान से एकत्रित समाधान "सी # यादृच्छिक संख्या जेनरेटर थ्रेड सुरक्षित है?"

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

जॉन स्कीट में इस विषय पर कुछ अच्छी पोस्ट हैं:

StaticRandom
यादृच्छिकता की समीक्षा करना

जैसा कि कुछ टिप्पणीकारों ने बताया है, Random अलग-अलग उदाहरणों का उपयोग करने में एक अन्य संभावित समस्या है, जो धागा-अनन्य हैं, लेकिन उन्हें समान रूप से सीड किया जाता है, और इसलिए छद्म यादृच्छिक संख्याओं के समान अनुक्रम को प्रेरित करता है, क्योंकि वे एक ही समय में या निकट एक दूसरे के अस्थायी निकटता उस मुद्दे को कम करने का एक तरीका कुछ यादृच्छिक बीज उत्पन्न करने और प्रत्येक दूसरे धागे के उपयोग के लिए नए Random उदाहरणों को प्रारंभ करने के लिए मास्टर Random उदाहरण (जो एक धागे द्वारा लॉक किया गया है) का उपयोग करना है।

नहीं, एक ही उदाहरण का उपयोग करके कई थ्रेड्स का उपयोग करके इसे सभी को तोड़ और वापस लौटा सकते हैं। हालांकि, एक धागा-सुरक्षित संस्करण (हर कॉल को Next() ) पर गंदा ताले की आवश्यकता के बिना सरल है। इस आलेख में विचार से अनुकूलित:

 public class ThreadSafeRandom { private static readonly Random _global = new Random(); [ThreadStatic] private static Random _local; public ThreadSafeRandom() { if (_local == null) { int seed; lock (_global) { seed = _global.Next(); } _local = new Random(seed); } } public int Next() { return _local.Next(); } } 

विचार प्रत्येक थ्रेड के लिए एक अलग static Random चर रखने के लिए है। स्पष्ट तरीके से ऐसा करना विफल रहता है, फिर भी, Random साथ एक अन्य मुद्दे की वजह से – यदि लगभग एक ही समय (लगभग 15ms के भीतर) में कई उदाहरण बनाए जाते हैं, तो वे सभी समान मूल्य वापस कर देंगे! इसे ठीक करने के लिए, हम प्रत्येक थ्रेड द्वारा उपयोग किए गए बीज उत्पन्न करने के लिए एक वैश्विक-स्थिर Random उदाहरण बनाते हैं।

उपरोक्त लेख, इस तरह से, कोड इन दोनों मुद्दों को Random साथ प्रदर्शित करता है

माइक्रोसॉफ्ट से आधिकारिक उत्तर बहुत मजबूत नहीं है http://msdn.microsoft.com/en-us/library/system.random.aspx#8 से :

रैंडम ऑब्जेक्ट थ्रेड सुरक्षित नहीं हैं यदि आपका ऐप कई थ्रेड्स से यादृच्छिक तरीके से कॉल करता है, तो आपको यह सुनिश्चित करने के लिए एक सिंक्रनाइज़ेशन ऑब्जेक्ट का उपयोग करना होगा कि केवल एक धागा एक समय में यादृच्छिक संख्या जनरेटर तक पहुंच सकता है। यदि आप यह सुनिश्चित नहीं करते हैं कि किसी रैंडम ऑब्जेक्ट को धागा-सुरक्षित तरीके से एक्सेस किया जाता है, तो उन विधियों को कॉल करता है जो यादृच्छिक संख्या वापस 0 पर लौटते हैं।

डॉक्स में बताए अनुसार, एक बहुत बुरा दुष्प्रभाव होता है, जो तब हो सकता है जब एक ही रैंडम ऑब्जेक्ट एकाधिक थ्रेड्स द्वारा उपयोग किया जाता है: यह केवल काम करना बंद कर देता है।

(यानी एक दौड़ की स्थिति है जो ट्रिगर होने पर, 'यादृच्छिक। अगली ….' तरीकों से वापसी मूल्य सभी बाद के कॉल के लिए 0 होगा।)

नहीं, यह धागा सुरक्षित नहीं है अगर आपको अलग थ्रेड्स से समान आवृत्ति का उपयोग करने की आवश्यकता है, तो आपको उपयोग को सिंक्रनाइज़ करना होगा।

मैं वास्तव में किसी भी कारण को नहीं देख सकता क्योंकि आपको इसकी ज़रूरत है, हालांकि। प्रत्येक धागे के लिए यह रैंडम कक्षा का अपना उदाहरण रखना अधिक कुशल होगा।

ThreadLocal<T> का उपयोग करने के लिए एक अन्य धागा सुरक्षित तरीका है:

 new ThreadLocal<Random>(() => new Random(GenerateSeed())); 

GenerateSeed() विधि को प्रत्येक बार यह याद दिलाने के लिए कहा जाता है कि यादृच्छिक संख्या अनुक्रम प्रत्येक थ्रेड में अद्वितीय हैं।

 static int SeedCount = 0; static int GenerateSeed() { return (int) ((DateTime.Now.Ticks << 4) + (Interlocked.Increment(ref SeedCount))); } 

छोटी संख्या में धागे के लिए काम करेंगे I

इसकी कीमत के लिए, यहां एक धागा-सुरक्षित, क्रिप्टोग्राफ़िक रूप से मजबूत आरएनजी है जो कि Random विरासत में Random

कार्यान्वयन में उपयोग में आसानी के लिए स्थैतिक प्रवेश बिंदु शामिल हैं, उनके पास सार्वजनिक आवृत्ति के तरीकों के समान नाम हैं लेकिन "जाओ" के साथ प्रीफ़िक्स हैं।

RNGCryptoServiceProvider.GetBytes लिए एक कॉल एक अपेक्षाकृत महंगा ऑपरेशन है। इसे आंतरिक बफर या "पूल" के उपयोग के द्वारा कम लगातार, और RNGCryptoServiceProvider का अधिक कुशल उपयोग करने के लिए कम किया जाता है। अगर किसी अनुप्रयोग डोमेन में कुछ पीढ़ियां हैं तो इसे ओवरहेड के रूप में देखा जा सकता है।

 using System; using System.Security.Cryptography; public class SafeRandom : Random { private const int PoolSize = 2048; private static readonly Lazy<RandomNumberGenerator> Rng = new Lazy<RandomNumberGenerator>(() => new RNGCryptoServiceProvider()); private static readonly Lazy<object> PositionLock = new Lazy<object>(() => new object()); private static readonly Lazy<byte[]> Pool = new Lazy<byte[]>(() => GeneratePool(new byte[PoolSize])); private static int bufferPosition; public static int GetNext() { while (true) { var result = (int)(GetRandomUInt32() & int.MaxValue); if (result != int.MaxValue) { return result; } } } public static int GetNext(int maxValue) { if (maxValue < 1) { throw new ArgumentException( "Must be greater than zero.", "maxValue"); } return GetNext(0, maxValue); } public static int GetNext(int minValue, int maxValue) { const long Max = 1 + (long)uint.MaxValue; if (minValue >= maxValue) { throw new ArgumentException( "minValue is greater than or equal to maxValue"); } long diff = maxValue - minValue; var limit = Max - (Max % diff); while (true) { var rand = GetRandomUInt32(); if (rand < limit) { return (int)(minValue + (rand % diff)); } } } public static void GetNextBytes(byte[] buffer) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (buffer.Length < PoolSize) { lock (PositionLock.Value) { if ((PoolSize - bufferPosition) < buffer.Length) { GeneratePool(Pool.Value); } Buffer.BlockCopy( Pool.Value, bufferPosition, buffer, 0, buffer.Length); bufferPosition += buffer.Length; } } else { Rng.Value.GetBytes(buffer); } } public static double GetNextDouble() { return GetRandomUInt32() / (1.0 + uint.MaxValue); } public override int Next() { return GetNext(); } public override int Next(int maxValue) { return GetNext(0, maxValue); } public override int Next(int minValue, int maxValue) { return GetNext(minValue, maxValue); } public override void NextBytes(byte[] buffer) { GetNextBytes(buffer); } public override double NextDouble() { return GetNextDouble(); } private static byte[] GeneratePool(byte[] buffer) { bufferPosition = 0; Rng.Value.GetBytes(buffer); return buffer; } private static uint GetRandomUInt32() { uint result; lock (PositionLock.Value) { if ((PoolSize - bufferPosition) < sizeof(uint)) { GeneratePool(Pool.Value) } result = BitConverter.ToUInt32( Pool.Value, bufferPosition); bufferPosition+= sizeof(uint); } return result; } } 

चूंकि Random धागा-सुरक्षित नहीं है, इसलिए आपको वैश्विक उदाहरण के बजाय एक प्रति धागा होना चाहिए। यदि आप इन एकाधिक Random कक्षाओं को एक ही समय में वरीयता देते हैं (यानी DateTime.Now.Ticks या ऐसा), तो आप उन सभी को बीज देने के लिए Guid उपयोग कर सकते हैं। गैर-पुनरावर्तनीय परिणाम सुनिश्चित करने के लिए, नेट Guid जनरेटर काफी लम्बाई के लिए जाता है, इसलिए:

 var rnd = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0)) 

प्रति प्रलेखन

इस प्रकार के किसी भी सार्वजनिक स्थिर (विजुअल बेसिक में साझा) थ्रेड सुरक्षित हैं किसी भी उदाहरण के सदस्यों को धागा सुरक्षित होने की गारंटी नहीं है

http://msdn.microsoft.com/en-us/library/system.random.aspx

RNGCryptoServiceProvider पर एक थ्रेड सुरक्षित यादृच्छिक नंबर जनरेटर के लिए देखें। डॉक्स से:

धागा सुरक्षा

इस प्रकार का धागा सुरक्षित है

नवीनीकृत: यह नहीं है। आपको या तो प्रत्येक कॉल पर रैंडम के एक उदाहरण का पुन: उपयोग करने की आवश्यकता है, जिसमें कुछ "सिकंदरा" ऑब्जेक्ट को लॉक करने के साथ। अगली () पद्धति या प्रत्येक ऐसे कॉल पर गारंटीकृत यादृच्छिक बीज के साथ एक नया उदाहरण का उपयोग करें। यससीर ने सुझाव दिया है कि आप एनईटी में क्रिप्टोग्राफी का उपयोग करके गारंटीकृत अलग बीज प्राप्त कर सकते हैं।

बीज के लिए लॉक-कम एल्गोरिदम का उपयोग करके पारंपरिक धागा स्थानीय भंडारण दृष्टिकोण में सुधार किया जा सकता है। जावा के एल्गोरिथम से संभवत: चुराया गया था (संभवतया उस पर भी सुधार ):

 public static class RandomGen2 { private static readonly ThreadLocal<Random> _rng = new ThreadLocal<Random>(() => new Random(GetUniqueSeed())); public static int Next() { return _rng.Value.Next(); } private const long SeedFactor = 1181783497276652981L; private static long _seed = 8682522807148012L; public static int GetUniqueSeed() { long next, current; do { current = Interlocked.Read(ref _seed); next = current * SeedFactor; } while (Interlocked.CompareExchange(ref _seed, next, current) != current); return (int)next ^ Environment.TickCount; } }