Кожен раз, коли ви new 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)