代码之家  ›  专栏  ›  技术社区  ›  user152949

在singleton中植入random()的最佳方法

  •  17
  • user152949  · 技术社区  · 15 年前

    我在单例类中有一个方法需要使用.NET系统。 Random() ,因为该方法是在多线程环境中调用的,所以我不能只创建一次并静态声明它,但必须创建一个 随机化() 每次调用方法时都调用。自从 随机化() 默认种子是基于时钟滴答的,在我的塞那里奥它不够随机。为了创建一个更好的种子,我研究了几种方法,并认为下面的方法是最好的,但可能还有其他(更快/更好)的方法可以做到这一点,我想知道。

    Random rnd = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0));
    
    4 回复  |  直到 12 年前
        1
  •  24
  •   Mark Seemann    15 年前

    与其尝试自己找到更好的种子,不如使用 System.Security.Cryptography.RandomNumberGenerator .

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

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

        2
  •  13
  •   James L    12 年前

    这是我的实现。螺纹安全,无锁紧。

    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);
        }
    }
    
        3
  •  3
  •   Guffa    15 年前

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

    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);
    
        4
  •  1
  •   Jim Lahman    12 年前

    使用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];
    
        }
    }