La réponse acceptée à this question, et une discussion similaire au travail aujourd'hui m'a amené à s'interroger sur quelque chose.Numéros aléatoires et stockage local thread
La question portait sur la façon de générer en toute sécurité des nombres aléatoires dans un programme multithread. La réponse acceptée préconise l'utilisation du stockage local des threads, créant ainsi un générateur de nombres aléatoires par thread. Je me demande si c'est vraiment une bonne idée. Supposons que deux threads démarrent en même temps (ce qui est tout à fait possible sur un système multicœur) et que tous deux appellent le constructeur par défaut Random
pour créer et initialiser un générateur de nombres aléatoires dans le stockage local de threads. Comme ils n'ont pas passé un paramètre de graine, Random
utilise l'heure du système comme graine. Donc, les deux générateurs de nombres aléatoires ont été initialisés avec la même graine. Ils généreront tous les deux la même séquence de nombres aléatoires.
Étant donné que ces threads sont alloués à partir du pool de threads, vous ne pouvez pas associer un objet particulier à un thread particulier. Ou, dans le cas de la question référencée ci-dessus, vous ne pouvez pas garantir quel thread de pool exécutera la requête suivante. Alors, imaginez que les éléments suivants se produit:
At startup, two requests come in simultaneously.
Two threads are created, each initializing a random number generator with the same seed.
Each thread generates three random numbers. They will be identical in both threads.
Next request comes in. It's assigned to thread #1.
It generates a random number and exits.
Some period of time elapses.
Next request comes in. It's assigned to thread #2.
It generates the same random number that thread #1 did just a while ago.
Cela pourrait se poursuivre indéfiniment, même si je doute que ce serait ping-ponging tout à fait mal. Le fait est que les deux threads ont le même PRNG et la probabilité de répéter une séquence est très élevée. Je comprends que le P dans PRNG signifie "pseudo", mais c'est un peu beaucoup.
Je pense qu'il est tout à fait possible que plusieurs threads initialisent une instance Random
avec la même valeur de départ. Si cela arrive, alors le "caractère aléatoire" d'au moins certaines choses dans l'application va en souffrir. Les implications de cela, bien sûr, dépendent de l'application. Ce que je ne sais pas, c'est que si les PRNG sont initialisés avec des graines différentes, est-ce que cela rend la séquence vue par un client plus aléatoire, moins aléatoire, ou à peu près la même chose? Autrement dit, si je devais écrire:
var rnd1 = new Random(123);
var rnd2 = new Random(654);
for (int i = 0; i < OneMillion; ++i)
{
numbers.Add(rnd1.Next());
numbers.Add(rnd2.Next());
}
Est-ce que la séquence de chiffres que je produis plus ou moins aléatoire que si je devais simplement générer deux millions de l'une des PRNGs?
Est-ce un problème pour votre application si, à chaque passage, vous générez la même séquence de nombres aléatoires? –
Parlez-vous de C#? – sje397
@Nader: La question est plus théorique que pratique, car je n'ai pas vraiment d'application particulière en tête. Mais disons que la réponse à votre question est oui. –