2011-01-06 19 views
8

tengo la siguiente claseRandom.Next() devuelve a veces mismo número en hilos separados

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 hilos, comienza cada una, y asigna cada hilo un azar device_id. 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.

+0

Esto es estadísticamente correcta, como si tiras 2 dados que en algún momento le dan el mismo número, más aleatoria no es seguro para subprocesos - > http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx – dvhh

+3

@Mitch: ninguna de las preguntas vinculadas tiene que ver con la misma situación. Es solo la seguridad del hilo lo que es relevante aquí, ya que solo hay una instancia de Random. –

+0

@Jon: sí, eso es cierto. –

Respuesta

23

Aleatorio no es seguro para subprocesos: no debe utilizar la misma instancia de varios subprocesos. Puede ser mucho peor que solo devolver los mismos datos: al utilizarlo desde varios hilos, puede "pegar" en un estado donde siempre devolver 0, IIRC.

Es obvio que no sólo quiere crear una nueva instancia para cada hilo más o menos al mismo tiempo, a medida que va a terminar con las mismas semillas ...

Tengo una article que entra en el detalles de esto y proporciona una implementación que ejemplifica perezosamente una instancia de Random por subproceso usando una semilla de incremento.

+0

Lo sospechaba pero no estaba seguro incluso después de comprobar MSDN. También revisaré tu artículo. Gracias. – dandan78

+0

Véase también [MiscUtil.StaticRandom] de Jon Skeet (http://www.yoda.arachsys.com/csharp/miscutil/). – Brian

4

Aleatorio 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. Por no mencionar que de acuerdo con el documentation:

los miembros de instancias no están garantizados para la ejecución de subprocesos.

Por lo tanto, no debe llamar al método Next en absoluto desde múltiples hilos.

1

Su código de ejemplo solo muestra un uso de _Random por subproceso. Suponiendo que este sea el caso, también podría generar el número aleatorio en el lazo 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 modificar su función del hilo para aceptar el parámetro:

static void Send(int device_id) 
{ 
    ... 
    //int device_id = _Random.Next(999999); 
    ... 
} 
Cuestiones relacionadas