c# - Random.Next() a veces devuelve el mismo número en hilos separados
multithreading (3)
Tengo la siguiente clase
class Program
{
static Random _Random = new Random();
static void Main(string[] args)
{
...
for (int i = 0; i < no_threads; ++i)
{
var thread = new Thread(new ThreadStart(Send));
thread.Start();
}
...
}
static void Send()
{
...
int device_id = _Random.Next(999999);
...
}
}
El código crea el número especificado de subprocesos, inicia cada uno y asigna a cada subproceso un device_id
aleatorio. Por alguna razón, los primeros dos hilos que se crean a menudo tienen el mismo device_id
. No puedo entender por qué sucede esto.
Aleatorio no es seguro para subprocesos: no debe usar la misma instancia de varios subprocesos. Puede ser mucho peor que solo devolver los mismos datos: al utilizarlo desde varios hilos, puede "atascarlo" en un estado en el que siempre devolverá 0, IIRC.
Obviamente, no solo desea crear una nueva instancia para cada hilo más o menos al mismo tiempo, ya que terminarán con las mismas semillas ...
Tengo un artículo que entra en los detalles de esto y proporciona una implementación que instantáneamente instancia una instancia de Random
por hilo usando una semilla en incremento.
Random es un generador de números pseudoaleatorio y no hay nada que le impida devolver el mismo resultado para varias llamadas. Después de todo, hay una probabilidad de que esto suceda. Sin mencionar que de acuerdo con la documentación :
No se garantiza que ningún miembro de instancia sea seguro para subprocesos.
Por lo tanto, no deberías llamar al método Next desde múltiples hilos.
Su código de ejemplo solo muestra un uso de _Random
por hilo. Suponiendo que este sea el caso, también podría generar el número aleatorio en el ciclo principal for
y pasar el número aleatorio en cada hilo como parámetro.
for (int i = 0; i < no_threads; ++i)
{
var thread = new Thread(new ThreadStart(Send));
thread.Start(_Random.Next(999999));
}
y luego modifique su función de hilo para aceptar el parámetro:
static void Send(int device_id)
{
...
//int device_id = _Random.Next(999999);
...
}