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 lockqui?
Fondamentalmente, Nextcambierà lo stato interno Randomdell'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é Randomfa 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
Randomistanze diverse per thread
Entrambi possono andare bene; ma il silenziamento di una singola istanza da più chiamanti contemporaneamente richiede solo problemi.
Il lockraggiunge 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)