在单例中种子Random()的最佳方法

时间:2009-09-09 11:13:53

标签: c# .net

我在单例类中有一个需要使用.NET系统的方法。 Random(),因为在多线程环境中调用该方法,我不能只创建一次并静态声明它,但每次调用该方法时我都必须创建一个Random()对象。由于Random()默认种子基于时钟滴答,因此在我的senario中它不够随机。为了创造一个更好的种子,我已经研究了几种方法并且认为以下一种方法是最好的,但可能有其他(更快/更好)的方法来做我想知道的。

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

4 个答案:

答案 0 :(得分:24)

不要试图自己想出更好的种子,而是使用System.Security.Cryptography.RandomNumberGenerator

它使用基于复杂算法的种子,该算法涉及许多不同的环境变量。系统时间就是其中之一,因为IIRC是你的网卡的MAC地址等等。

它也被认为是比随机类实现的算法更“随机”的算法。

答案 1 :(得分:13)

这是我的实施。线程安全,无锁定。

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);
    }
}

答案 2 :(得分:3)

静态创建它并使用锁来使其线程安全:

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);

答案 3 :(得分:1)

利用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];

    }
}