每个线程的另一个随机数

时间:2014-05-12 16:32:01

标签: c# multithreading

我有简单的类生成随机数:

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());
    }
} 

所以主要是我:

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

我的问题是如何才能为每个帖子获取另一个数字?

2 个答案:

答案 0 :(得分:3)

您需要使用所谓的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();
}

答案 1 :(得分:0)

当您调用Random rnd = new Random();时,随机数生成器的种子将根据系统时钟进行初始化。那时钟的分辨率并不是那么好(我不记得频率,但我相信它每秒不到100个滴答)。因此,两个线程使用系统时钟同时在Random的实例中创建,因此两者都具有相同的种子。

种子决定了它将产生的伪随机数序列。由于两个线程都获得相同的种子,因此两者都可以产生相同的序列。

最佳解决方案是仅创建一个Random对象的实例并将其传递给您的线程(并可能保护对它的访问,因为我不确定它是否是MT安全的。)

另一个是提供一些其他种子生成器而不是默认的种子生成器,例如将系统时间与线程id或类似网格结合起来(请注意,作为种子的托管线程id可能不够,因为托管线程ID通常倾向于挂起较低的范围,因此你的随机种子将是非常可预测的,因此根本不是随机的。)