在单例中种子Random()的最佳方法
我在单例类中有一个需要使用.NET系统的方法。 Random()
,因为在multithreading环境中调用该方法,我不能只创建一次并静态声明它,但每次调用该方法时我都必须创建一个Random()
对象。 由于Random()
默认种子基于时钟滴答,因此在我的senario中它不够随机。 为了创造一个更好的种子,我已经研究了几种方法并且认为以下一种方法是最好的,但可能还有其他(更快/更好)的方法来做我想知道的。
Random rnd = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0));
不要试图自己想出更好的种子,而是使用System.Security.Cryptography.RandomNumberGenerator 。
它使用基于复杂算法的种子,该算法涉及许多不同的环境变量。 系统时间就是其中之一,因为IIRC是你的网卡的MAC地址等。
它也被认为是比Random类实现的算法更“随机”的算法。
这是我的实施。 线程安全,无锁定。
public static class StrongRandom { [ThreadStatic] private static Random _random; public static int Next(int inclusiveLowerBound, int inclusiveUpperBound) { if (_random == null) { var cryptoResult = new byte[4]; new RNGCryptoServiceProvider().GetBytes(cryptoResult); int seed = BitConverter.ToInt32(cryptoResult, 0); _random = new Random(seed); } // upper bound of Random.Next is exclusive int exclusiveUpperBound = inclusiveUpperBound + 1; return _random.Next(inclusiveLowerBound, exclusiveUpperBound); } }
静态创建它并使用锁来使其线程安全:
public static class RandomProvider { private static Random _rnd = new Random(); private static object _sync = new object(); public static int Next() { lock (_sync) { return _rnd.Next(); } } public static int Next(int max) { lock (_sync) { return _rnd.Next(max); } } public static int Next(int min, int max) { lock (_sync) { return _rnd.Next(min, max); } } }
如果由于某种原因在每个线程中仍然需要Random
对象,则可以使用静态类来为它们设定种子:
Random r = new Random(RandomProvider.Next() ^ Environment.TickCount);
使用RNGCryptoServiceProvider生成随机数的示例程序
class Program { public static void Main(string[] args) { int i; byte bRandom; String sL; for (i = 0; i < 10; i++) { bRandom = GetRandom(); sL = string.Format("Random Number: {0}", bRandom); Console.WriteLine(sL); } Console.ReadLine(); } public static byte GetRandom() { RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider(); // Create a byte array to hold the random value. byte[] randomNumber = new byte[1]; rngCsp.GetBytes(randomNumber); return randomNumber[0]; } }