在多线程应用程序中使用Random的正确方法

时间:2013-10-09 11:14:30

标签: c# random

确定。以下是我所知道的不起作用:

int Rand()
{
    //will return the same number over and over again
    return new Random().Next();
}

static Random rnd=new Random();

int Rand()
{
    //if used like this from multiple threads, rnd will dissintegrate 
    //over time and always return 0
    return rnd.Next();
}

这将正常工作,但如果由多个线程使用,CPU使用率会上升,我不想要,而且我认为没有必要:

int Rand()
{
    lock(rnd)
    {
        return rnd.Next();
    }
}

那么,c#是否有一个线程安全的Random类,或者更好的方法来使用它?

4 个答案:

答案 0 :(得分:60)

我使用这样的东西:

public static class StaticRandom
{
    static int seed = Environment.TickCount;

    static readonly ThreadLocal<Random> random =
        new ThreadLocal<Random>(() => new Random(Interlocked.Increment(ref seed)));

    public static int Rand()
    {
        return random.Value.Next();
    }
}

答案 1 :(得分:12)

readonly ThreadLocal<Random> random = 
    new ThreadLocal<Random>(() => new Random(GetSeed()));

int Rand()
{
    return random.Value.Next();
}

static int GetSeed()
{
    return Environment.TickCount * Thread.CurrentThread.ManagedThreadId;
}

(从Jeroen Vannevel的评论中无耻地偷走)

答案 2 :(得分:5)

我认为你想要的是线程静态的

[ThreadStatic]
static Random rnd=new Random();

int Rand()
{
    if ( rnd == null ) 
    {
       rnd = new Random()
    }
    //Now each thread gets it's own version
    return rnd.Next();
}

这样每个线程都会获得自己的rnd属性版本

你的锁定会增加cpu使用率的原因是因为所有线程都会在这一点上等待(如果你经常使用它就应该是一个问题)

[更新]我修复了初始化。有人指出它确实留下了这样一个事实:如果你在相同的毫秒内启动多个线程,那么它们将产生相同的结果。

答案 3 :(得分:0)

我的小组最近调查了这个。我们得出的结论是,我们应该使用专门设计用于支持并行计算的随机数生成器。 Tina的随机数生成器库(http://numbercrunch.de/trng/)具有稳定的实现,以及具有理论介绍和相关文献参考的手册。到目前为止,我们对它非常满意。