Chaque fois que vous le faites, new Random()
il est initialisé à l'aide de l'horloge. Cela signifie que dans une boucle serrée, vous obtenez souvent la même valeur. Vous devez conserver une seule instance aléatoire et continuer à utiliser Next sur la même instance.
//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);
}
}
Edit (voir commentaires): pourquoi avons-nous besoin d'un lock
ici?
Fondamentalement, Next
va changer l'état interne de l' Random
instance. Si nous le faisons en même temps à partir de plusieurs threads, vous pourriez dire "nous venons de rendre le résultat encore plus aléatoire", mais ce que nous faisons en fait est potentiellement de casser l'implémentation interne, et nous pourrions également commencer à obtenir les mêmes chiffres à partir de différents threads, ce qui pourrait être un problème - et peut-être pas. La garantie de ce qui se passe en interne est le plus gros problème, cependant; car Random
ne pas faire aucune garantie de fil de sécurité. Il existe donc deux approches valides:
- Synchronisez afin de ne pas y accéder en même temps à partir de différents threads
- Utiliser différentes
Random
instances par thread
Soit peut être bien; mais mutexer une seule instance de plusieurs appelants en même temps ne fait que demander des ennuis.
Le lock
réalise la première (et la plus simple) de ces approches; cependant, une autre approche pourrait être:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
c'est alors par thread, vous n'avez donc pas besoin de synchroniser.
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
ne donne pas de meilleurs nombres "aléatoires" que.Next(0, 256)