C# Random.Next внезапно перестает возвращать случайные значения [дубликаты]

Возможный дубликат:
System.Random продолжает возвращать одно и то же значение

Я реорганизую и расширяю небольшую модель на основе агентов C#, чтобы помочь некоторым профессорам биологии предсказать распространение болезни. Каждый год симуляции каждый отдельный агент случайным образом перемещается в ближайший узел населения, возможно, распространяя болезнь. Я новичок в C#, но я читал о потенциальных проблемах с Random.Next, возвращающим одно и то же значение при повторной инициализации с тем же системным временем. Чтобы избежать этого, я создал статический экземпляр, на который ссылаются для каждого нового случайного значения.

Особенности:

Пытаясь увеличить масштаб модели, я изменил ее, чтобы параллельно вычислять информацию о «путешествии» для каждого узла населения. При тестировании модели я заметил, что в новой версии болезнь не распространялась дальше первого года. Дальнейшее расследование сузило проблему до перемещения между узлами. После первого года все агенты оставались неподвижными. Я изучил функцию, отвечающую за их перемещение, и обнаружил, что она работает, создавая список всех ближайших узлов, генерируя случайное число ‹= количеству элементов в списке и перемещаясь к listOfNearbyNodes[myRandomNumber].

Эта проблема:

Затем я добавил оператор печати для вывода значения случайного индекса для каждой итерации. Я обнаружил, что вся модель работает точно так, как ожидалось, в течение первого года симуляции, при этом случайные числа генерируются в приемлемом диапазоне. Однако после окончания первого года и циклов симуляции точно такой же код будет возвращать только «случайный» индекс, равный 0. Каждый поток, каждая итерация, каждый узел, каждый агент — всегда 0. Поскольку текущий узел агента всегда первый элемент в списке агенты больше никогда не перемещают.

Я подумал, что это может быть еще одним проявлением ошибки начального значения системного времени, поэтому я пробовал три разных способа реализации статического случайного объекта, но это не помогает. Каждый раз, когда я запускаю симуляцию, первый год всегда работает правильно, а затем Random.Next() начинает возвращать только 0.

Есть ли у кого-нибудь идеи относительно того, где я должен искать ошибку? Спасибо!


person Mandelbrot    schedule 07.07.2010    source источник
comment
Короткий, но полный пример кода, воспроизводящий ошибку, будет полезен как вам, так и сообществу SO, помогая диагностировать проблему.   -  person LBushkin    schedule 07.07.2010
comment
Я задал вопрос, который, как мне кажется, связан и может помочь: stackoverflow.com/questions/2924599/   -  person Mathias    schedule 07.07.2010


Ответы (4)


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

Опции:

  • Создайте новый экземпляр Random для каждого потока (здесь может помочь ThreadStatic)
  • Используйте один экземпляр Random, но только в замке.

У меня есть сообщение в блоге с примером кода , но, пожалуйста, прочитайте комментарии, так как есть хорошие предложения по его улучшению. Я планирую написать еще одну статью о случайности в ближайшем будущем...

person Jon Skeet    schedule 07.07.2010

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

Вы можете оформить статическую переменную, содержащую ссылку на класс Random, как ThreadStatic, что позволит вам поддерживать отдельный экземпляр для каждого потока:

[ThreadStatic]
private static Random m_Random;  // don't attempt to initialize this here...

public void YourThreadStartMethod()
{
    // initialize each random instance as each thread starts...
    m_Random = new Random();
}

Если вы используете .NET 4.0, есть также класс ThreadLocal<T>, что помогает упростить инициализацию одного экземпляра для каждого потока.

person LBushkin    schedule 07.07.2010


Я думаю, вам следует вместо этого использовать RNGCryptoServiceProvider

http://msdn.microsoft.com/en-us/library/system.security.cryptography.rngcryptoserviceprovider.aspx

person Fosco    schedule 07.07.2010