У меня есть следующая функция:
//Function to get random number
public static int RandomNumber(int min, int max)
{
Random random = new Random();
return random.Next(min, max);
}
Как я это называю:
byte[] mac = new byte[6];
for (int x = 0; x < 6; ++x)
mac[x] = (byte)(Misc.RandomNumber((int)0xFFFF, (int)0xFFFFFF) % 256);
Если я выполняю этот цикл с помощью отладчика во время выполнения, я получаю разные значения (что я и хочу). Однако, если я поставлю точку останова на две строки ниже этого кода, все члены mac
массива будут иметь одинаковое значение.
Почему это происходит?
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
не дает лучших «случайных» чисел, чем.Next(0, 256)
Rand.Next(int, int)
метод, который обеспечивает статический доступ к случайным значениям, не блокируя и не сталкиваясь с проблемой повторного использованияОтветы:
Каждый раз, когда вы делаете
new Random()
это, инициализируется с помощью часов. Это означает, что в тесном цикле вы получаете одно и то же значение много раз. Вы должны сохранить один экземпляр Random и продолжать использовать Next на том же экземпляре.Редактировать (см. Комментарии): зачем нам
lock
здесь?В основном,
Next
собирается изменить внутреннее состояниеRandom
экземпляра. Если мы сделаем это одновременно из нескольких потоков, вы можете возразить: «Мы только что сделали результат еще более случайным», но то, что мы на самом деле делаем, потенциально нарушает внутреннюю реализацию, и мы также можем начать получать те же цифры из разных тем, что может быть проблемой - а может и нет. Гарантия того, что происходит внутри, является более важной проблемой; так какRandom
это не делает никаких гарантий безопасности потоков. Таким образом, есть два правильных подхода:Random
экземпляры на потокЛибо может быть хорошо; но мьютекс одного экземпляра от нескольких абонентов одновременно просто напрашивается на неприятности.
lock
Достигает первые (и проще) эти подходы; Тем не менее, другой подход может быть:тогда это для каждого потока, поэтому вам не нужно синхронизировать.
источник
lock (syncObject)
поможет только если всеrandom.Next()
звонки тоже внутриlock (syncObject)
. Если описанный вами сценарий действительно происходит даже при правильномlock
использовании, он также очень вероятно случается в однопоточном сценарии (напримерRandom
, слегка нарушается).Для удобства повторного использования в вашем приложении статический класс может помочь.
Вы можете использовать затем использовать статический случайный экземпляр с кодом, таким как
источник
Решение Марка может быть довольно дорогим, поскольку оно должно синхронизироваться каждый раз.
Мы можем обойти необходимость синхронизации с помощью шаблона хранения для конкретного потока:
Измерьте две реализации, и вы увидите значительную разницу.
источник
Random
экземпляра для получения семени - хорошая идея. Также обратите внимание, что код можно еще более упростить, используяThreadLocal<T>
класс, представленный в .NET 4 (как Фил также написал ниже ).Мой ответ отсюда :
Просто повторяя правильное решение :
Так что вы можете позвонить:
все на протяжении
Если вам строго необходим статический метод без сохранения состояния для генерации случайных чисел, вы можете положиться на
Guid
.Это будет немного медленнее, но может быть гораздо более случайным, чем
Random.Next
, по крайней мере, из моего опыта.Но не :
Создание ненужного объекта замедлит работу, особенно в цикле.
И никогда :
Мало того, что он медленнее (внутри цикла), его случайность ... ну, на мой взгляд, не очень хороша ..
источник
Random
класс соответствует случаю 2 (таким образом, случай 1 тоже). Вы можете заменить использованиеRandom
только вашим,Guid+Hash
если вы не в случае 2. Случай 1, вероятно, достаточно, чтобы ответить на вопрос, а затем, всеGuid+Hash
работает нормально. Но это не ясно сказано (пс: это униформа )Random
иGuid.NewGuid().GetHashCode()
через Ent ( fourmilab.ch/random ), и оба они одинаково случайны.new Random(Guid.NewGuid().GetHashCode())
работает так же хорошо, как и использование синхронизированного «мастера»Random
для генерацииRandom
начальных чисел для «дочерних» объектов. Конечно, это зависит от того, как ваша система генерирует Guids - для моей системы они довольно случайны, а для других это может даже быть крипто-случайным. Итак, Windows или MS SQL в настоящее время выглядят хорошо. Моно и / или мобильный может отличаться.GetHashCode
Guid в .NET является производным от его строкового представления. Вывод на мой взгляд довольно случайный.Я бы предпочел использовать следующий класс для генерации случайных чисел:
источник
1) Как сказал Марк Гравелл, попробуйте использовать ОДИН генератор случайных чисел. Всегда здорово добавить это в конструктор: System.Environment.TickCount.
2) Один совет. Допустим, вы хотите создать 100 объектов и предположить, что у каждого из них должен быть свой собственный генератор случайных чисел (удобно, если вы вычисляете НАГРУЗКИ случайных чисел за очень короткий период времени). Если бы вы делали это в цикле (создание 100 объектов), вы могли бы сделать это так (чтобы обеспечить полную случайность):
Приветствия.
источник
Random()
конструктор по умолчанию вызываетRandom(Environment.TickCount)
Каждый раз, когда вы выполняете
Неважно, если вы выполните его миллионы раз, вы всегда будете использовать одно и то же семя.
Если вы используете
Вы получаете другую последовательность случайных чисел, если хакер угадает семя, и ваш алгоритм связан с безопасностью вашей системы - ваш алгоритм нарушен. Я тебя выполню мульт. В этом конструкторе начальное число определяется системными часами, и, если несколько экземпляров создаются за очень короткий период времени (миллисекунды), возможно, что они могут иметь одинаковое начальное число.
Если вам нужны безопасные случайные числа, вы должны использовать класс
Применение:
источник
It does not matter if you execute it millions of times, you will always use the same seed.
Это неправда, если вы сами не укажете семя.просто объявите переменную класса Random следующим образом:
если вы хотите получать разные случайные числа каждый раз из своего списка, используйте
Каждый раз, объявив
Random r = new Random()
один раз.источник
new Random()
он использует системные часы, но если вы вызываете весь этот код дважды подряд, прежде чем часы изменятся, вы получите одно и то же случайное число. Вот и весь смысл ответов выше.Есть много решений, здесь одно: если вы хотите, чтобы только цифры стерли буквы, а метод получил случайное число и длину результата.
источник
Random
экземпляр, но вы все еще ожидаете, что вызывающая сторона создаст общий экземпляр. Если вызывающий объект создает новый экземпляр каждый раз, а код выполняется дважды до изменения часов, вы получите одно и то же случайное число. Таким образом, этот ответ все еще делает предположения, которые могут быть ошибочными.