Ogni volta che lo fai new Random()
viene inizializzato usando l'orologio. Ciò significa che in un ciclo stretto si ottiene lo stesso valore molte volte. Dovresti conservare una singola istanza casuale e continuare a usare Next nella stessa istanza.
//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);
}
}
Modifica (vedi commenti): perché abbiamo bisogno di un lock
qui?
Fondamentalmente, Next
cambierà lo stato interno Random
dell'istanza. Se lo facciamo allo stesso tempo da più thread, si potrebbe obiettare: "Abbiamo appena fatto il risultato ancora più casuale", ma quello che stiamo effettivamente facendo è potenzialmente rompendo l'implementazione interna, e potremmo anche iniziare a ricevere gli stessi numeri da thread diversi, che potrebbe essere un problema - e potrebbe non esserlo. La garanzia di ciò che accade internamente è il problema più grande, però; poiché Random
fa non fornire alcuna garanzia di filo di sicurezza. Quindi ci sono due approcci validi:
- Sincronizza in modo da non accedervi contemporaneamente da thread diversi
- Usa
Random
istanze diverse per thread
Entrambi possono andare bene; ma il silenziamento di una singola istanza da più chiamanti contemporaneamente richiede solo problemi.
Il lock
raggiunge la prima (e più semplice) di questi approcci; tuttavia, un altro approccio potrebbe essere:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
questo è quindi per thread, quindi non è necessario sincronizzare.
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
non si.Next(0, 256)