【问题标题】:Another random number per every thread每个线程的另一个随机数
【发布时间】:2014-05-13 00:44:46
【问题描述】:

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

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

我的问题是我可以做些什么来为每个线程获取另一个数字?

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 2013-02-02
        • 1970-01-01
        • 2015-09-13
        • 2011-03-18
        • 1970-01-01
        • 1970-01-01
        • 2013-12-07
        • 1970-01-01
        相关资源
        最近更新 更多