📅  最后修改于: 2023-12-03 15:13:53.288000             🧑  作者: Mango
在 C# 中,随机数生成器需要一个种子来确定随机数序列的起始值。随机种子是一个整数,指示生成器开始随机数序列的位置。
Random random = new Random(seed);
在上面的代码中,我们使用 seed
初始化了一个 Random
实例。seed
可以是任意整数,通常使用当前系统时间的毫秒数来作为种子值。
在随机数生成器生成序列时,如果使用相同的种子值,则生成的序列也将是相同的。因此,在实际应用中,我们通常针对不同的需求使用不同的种子值。
为了确保生成的随机数序列具有更好的随机性,我们可以使用 Guid
或 System.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
方法则可以使用任意线程调用,对应用程序的其它部分提供独立的随机数序列。