每个线程另一个随机数
本文关键字:随机数 另一个 线程 | 更新日期: 2023-09-27 18:03:01
我有一个简单的类来生成随机数:
public class Bar
{
Random rnd = new Random();
public int GenerateRandomNumber()
{
return rnd.Next(1, 100);
}
}
然后我在第二类中使用它,在那里我创建两个线程。每个线程都使用bar类的函数写控制台自己的id和随机数。如下所示:
public class Foo
{
Thread t1;
Thread t2;
Bar bar;
public Foo(Bar bar)
{
t1 = new Thread(GetRandomNumber);
t2 = new Thread(GetRandomNumber);
this.bar = bar;
}
public void Start()
{
t1.Start();
t2.Start();
}
private void GetRandomNumber()
{
Console.WriteLine("Thread {0} {1}", Thread.CurrentThread.ManagedThreadId,bar.GenerateRandomNumber());
}
}
那么在main中我有:
static void Main(string[] args)
{
Bar bar1 = new Bar();
Bar bar2 = new Bar();
Foo f1 = new Foo(bar1);
Foo f2 = new Foo(bar2);
f1.Start();
f2.Start();
Console.ReadLine();
}
在控制台中,我可以得到例如:
Thread 11 34
Thread 12 9
Thread 13 34
Thread 14 9
我的问题是我能做些什么来获得每个线程的另一个数字?
您需要用所谓的seed
初始化随机生成器,这对于不同的线程是不同的。最简单的方法是:
Random rnd = new Random(Thread.CurrentThread.ManagedThreadId);
在你发布的代码中,简单地修改一行是没有用的。
为了它的工作,你必须改变它的方式,使每个线程都有自己的Random
实例。就像这样:
public class Foo
{
Thread t1;
Thread t2;
public Foo(Func<Bar> getBar)
{
t1 = new Thread(()=>GetRandomNumber(getBar()));
t2 = new Thread(()=>GetRandomNumber(getBar()));
}
public void Start()
{
t1.Start();
t2.Start();
}
private void GetRandomNumber(Bar bar)
{
Console.WriteLine("Thread {0} {1}", Thread.CurrentThread.ManagedThreadId,bar.GenerateRandomNumber());
}
}
static void Main(string[] args)
{
Foo f1 = new Foo(()=>new Bar());
Foo f2 = new Foo(()=>new Bar());
f1.Start();
f2.Start();
Console.ReadLine();
}
调用Random rnd = new Random();
时,将根据系统时钟初始化随机数生成器的种子。那个时钟的分辨率不是很好(我不记得频率了,但我相信它每秒不到100次)。因此,您的两个线程使用系统时钟同时在Random
实例中创建,因此它们具有相同的种子。
Seed决定了它将生成的伪随机数序列。由于两个线程获得相同的种子,因此可以得到相同的序列。
最好的解决方案是只创建一个Random
对象的实例并将其传递给您的线程(并可能保护对它的访问,因为我不确定它是否mt安全)。
另一种方法是提供一些其他的种子生成器而不是默认的,例如将系统时间与线程id或类似的网格相结合(注意,仅将托管线程id作为种子可能不够,因为托管线程id通常倾向于挂在较低的范围内,因此您的随机种子将非常可预测,因此根本不是随机的)。