Каждый раз, когда вы делаете new Random()
это, инициализируется с помощью часов. Это означает, что в тесном цикле вы получаете одно и то же значение много раз. Вы должны сохранить один экземпляр Random и продолжать использовать Next на том же экземпляре.
//Function to get a random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}
Редактировать (см. Комментарии): зачем нам lock
здесь?
В основном, Next
собирается изменить внутреннее состояние Random
экземпляра. Если мы сделаем это одновременно из нескольких потоков, вы можете возразить: «Мы только что сделали результат еще более случайным», но то, что мы на самом деле делаем, потенциально нарушает внутреннюю реализацию, и мы также можем начать получать те же цифры из разных тем, что может быть проблемой - а может и нет. Гарантия того, что происходит внутри, является более важной проблемой; так как Random
это не делает никаких гарантий безопасности потоков. Таким образом, есть два правильных подхода:
- Синхронизировать, чтобы мы не обращались к нему одновременно из разных потоков
- Используйте разные
Random
экземпляры на поток
Либо может быть хорошо; но мьютекс одного экземпляра от нескольких абонентов одновременно просто напрашивается на неприятности.
lock
Достигает первые (и проще) эти подходы; Тем не менее, другой подход может быть:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
тогда это для каждого потока, поэтому вам не нужно синхронизировать.
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
не дает лучших «случайных» чисел, чем.Next(0, 256)