Генератор случайных чисел C#, застревающий в цикле

Я использую.NET для создания искусственной жизненной программы, и я использую псевдослучайный класс C#, определенный в Singleton. Идея состоит в том, что, если я использую тот же генератор случайных чисел всюду по приложению, я мог бы просто сохранить семя и затем перезагрузить от семени для перевычислений определенного интересного выполнения.

public sealed class RandomNumberGenerator : Random
{
    private static readonly RandomNumberGenerator instance = new RandomNumberGenerator();

    RandomNumberGenerator()
    {

    }

    public static RandomNumberGenerator Instance
    {
        get
        {
            return instance;
        }
    }
}

Я также хотел метод, который мог дать мне два различных случайных числа.

public static Tuple<int, int> TwoDifferentRandomNumbers(this Random rnd, int minValue, int maxValue)
    {
        if (minValue >= maxValue)
            throw new ArgumentOutOfRangeException("maxValue", "maxValue must be greater than minValue");
        if (minValue + 1 == maxValue)
            return Tuple.Create<int, int>(minValue, maxValue);

        int rnd1 = rnd.Next(minValue, maxValue);
        int rnd2 = rnd.Next(minValue, maxValue);
        while (rnd1 == rnd2)
        {                
            rnd2 = rnd.Next(minValue, maxValue);
        }
        return Tuple.Create<int, int>(rnd1, rnd2);            
    }

Проблема иногда - это rnd.Next(minValue,maxValueвсегда возвраты minValue. Если я устанавливаю контрольные точки в этой точке и пытаюсь создать двойное и установить ее на rnd.NextDouble(), это возвращается 0.0. Кто-либо знает, почему это происходит?

Я знаю, что это - генератор псевдослучайных чисел, но откровенно говоря, я не ожидал, что это заблокирует в 0. К генератору случайных чисел получают доступ от нескольких потоков... это могло быть источником проблемы?

РЕДАКТИРОВАНИЕ: Спасибо, проблема закончила тем, что была потокобезопасностью.

Это - новая версия класса.

 public sealed class RandomNumberGenerator : Random
{
    private static Random _global = new Random();
    [ThreadStatic]
    private static Random _localInstance;

    RandomNumberGenerator()
    {

    }

    public static Random Instance
    {
        get
        {
            Random inst = _localInstance;
            if (inst == null)
            {
                int seed;
                lock (_global) seed = _global.Next();
                _localInstance = inst = new Random(seed);
            }
            return _localInstance;
        }
    }
}
5
задан Jean Azzopardi 26 April 2010 в 17:36
поделиться

4 ответа

Если вы используете только один RNG для нескольких потоков, даже если вы сохраните начальное число, вы не сможете сгенерировать то же самое. числа при следующем запуске приложения, потому что вы не будете уверены, что вызовы ГСЧ из разных потоков будут в том же порядке.

Если у вас есть фиксированное / известное количество потоков, создайте ГСЧ для каждого потока и сохраните каждое начальное число.

Забудьте то, что я только что сказал, если вы на 100% уверены, что каждый поток будет вызывать ГСЧ в том же порядке, что и в прошлый раз, если вы используете одно и то же начальное число.

3
ответ дан 18 December 2019 в 10:42
поделиться

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

На самом деле для этого не требуется одноэлементный экземпляр ГСЧ. Если вы инициализируете два отдельных экземпляра Random одним и тем же начальным числом , они будут производить точно такую ​​же последовательность.

Мой совет: сохраните семя, но избавьтесь от синглтона.

1
ответ дан 18 December 2019 в 10:42
поделиться

Класс Random не является потокобезопасным.

Вы должны сделать свой статический экземпляр [ThreadStatic] или защитить его блокировкой.

11
ответ дан 18 December 2019 в 10:42
поделиться

Мне даже не нужно искать класс Random, чтобы понять, что "все методы экземпляра этого класса не потокобезопасны". Это относится ко всем классам .NET, за очень немногими исключениями.

Так что да, это многопоточность. Но вы также не упомянули о проверке того, что MaxValue > MinValue.

1
ответ дан 18 December 2019 в 10:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: