48

好的。这是我所知道的行不通的:

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

4 回答 4

76

我使用这样的东西:

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();
    }
}
于 2013-10-09T11:41:56.603 回答
13
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 的评论中窃取)

于 2013-10-09T11:39:19.887 回答
6

我认为你想要的是 threadstatic

[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 使用率的原因是因为所有线程都将在该单点上等待(如果您经常使用它应该只是一个问题)

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

于 2013-10-09T11:28:36.867 回答
0

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

于 2013-10-09T16:26:28.323 回答