📜  c#中的随机种子(1)

📅  最后修改于: 2023-12-03 15:13:53.288000             🧑  作者: Mango

C# 中的随机种子

在 C# 中,随机数生成器需要一个种子来确定随机数序列的起始值。随机种子是一个整数,指示生成器开始随机数序列的位置。

Random random = new Random(seed);

在上面的代码中,我们使用 seed 初始化了一个 Random 实例。seed 可以是任意整数,通常使用当前系统时间的毫秒数来作为种子值。

在随机数生成器生成序列时,如果使用相同的种子值,则生成的序列也将是相同的。因此,在实际应用中,我们通常针对不同的需求使用不同的种子值。

为了确保生成的随机数序列具有更好的随机性,我们可以使用 GuidSystem.Security.Cryptography.RandomNumberGenerator 等密钥生成器来生成随机种子。

var randomSeed = new byte[4];

using (var cryptor = new System.Security.Cryptography.RNGCryptoServiceProvider())
{
    cryptor.GetBytes(randomSeed);
}

int seed = BitConverter.ToInt32(randomSeed, 0);

在上面的代码中,我们利用 RNGCryptoServiceProvider 生成了一个长度为 4 的 byte 数组,并使用 BitConverter.ToInt32 将其转换为整数作为种子值。

需要注意的是,在多线程环境中使用随机数生成器时,需要对随机生成器进行同步处理,以保证生成的随机数序列不会被多个线程同时访问或修改。一种经典的方案是使用线程本地存储方式,即每个线程都生成一个独立的随机数生成器实例。

private static readonly ThreadLocal<Random> RandomGenerator = new ThreadLocal<Random>(() => new Random(GenerateRandomSeed()));

private static int GenerateRandomSeed()
{
    var randomSeed = new byte[4];

    using (var cryptor = new System.Security.Cryptography.RNGCryptoServiceProvider())
    {
        cryptor.GetBytes(randomSeed);
    }

    return BitConverter.ToInt32(randomSeed, 0);
}

public static int GenerateRandomNumber()
{
    return RandomGenerator.Value.Next();
}

上述代码中,我们将线程本地存储的随机数生成器实例初始化为一个 lambda 表达式,该表达式生成了一个新的随机数生成器实例,并使用 GenerateRandomSeed 方法生成一个随机种子作为初始值。而 GenerateRandomNumber 方法则可以使用任意线程调用,对应用程序的其它部分提供独立的随机数序列。