Подтвердить что ты не робот

Правильный способ использования Random в многопоточном приложении

Ok. Вот что я знаю, что не получится:

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

Это будет работать корректно, но если используется несколькими потоками, загрузка процессора идет вверх, чего я не хочу, и который, я думаю, не нужен:

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

Итак, существует ли потокобезопасный класс Random для С# или лучший способ его использования?

4b9b3361

Ответ 1

Я использую что-то вроде этого:

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

Ответ 2

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)

Ответ 3

Я думаю, что вы хотите использовать threadstatic

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

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

Таким образом, каждый поток получает свою собственную версию вашего свойства rnd

Причина, по которой ваша блокировка увеличит использование процессора, - это то, что все потоки будут ждать в этой единственной точке (это должно быть проблемой, если вы используете ее много)

[Обновление] я исправлена ​​инициализация. Как заметил кто-то, он оставляет тот факт, что если вы начнете несколько потоков в тот же самый milisecond, тогда они будут давать одинаковые результаты.

Ответ 4

Моя группа недавно изучила это. Мы пришли к выводу, что мы должны использовать генератор случайных чисел, специально разработанный для поддержки параллельных вычислений. Библиотека генераторов случайных чисел Тины (http://numbercrunch.de/trng/) имеет стабильную реализацию и руководство с теоретическим введением и ссылками на соответствующую литературу. До сих пор мы очень довольны этим.