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