Correct way to use Random in multithread applicati

2019-01-13 20:15发布

This question already has an answer here:

Ok. Here is what I know that won't work:

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

This will work correctly, but if used by multiple threads, the CPU usage goes way up, which I don't want, and which I think is not necessary:

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

So, is there a thread-safe Random class for c#, or a better way to use it?

标签: c# random
4条回答
The star\"
2楼-- · 2019-01-13 20:29

I use something like this:

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();
    }
}
查看更多
Lonely孤独者°
3楼-- · 2019-01-13 20:31

My group recently looked into this. We came to the conclusion that we should use a random number generator that has been specifically designed to support parallel computing. Tina's Random Number Generator Library (http://numbercrunch.de/trng/) has a stable implementation, and a manual with a theoretical introduction and references to the relevant literature. So far, we are very satisfied with it.

查看更多
趁早两清
4楼-- · 2019-01-13 20:50

I think what you want is 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();
}

That way each thread get their own version of your rnd property

The reason your locking will increase cpu usage is because all threads will wait on that single point (should only be an issue if you use it a lot)

[Update] i fixed the initialization. As someone pointed out it does leave the fact that if you start multiple threads in the same milisecond then they will produce the same results.

查看更多
beautiful°
5楼-- · 2019-01-13 20:54
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;
}

(shamelessly stolen from the comment of Jeroen Vannevel)

查看更多
登录 后发表回答