2011-01-06 4 views
8

Ich habe folgende KlasseRandom.Next() gibt manchmal gleiche Anzahl in getrennten Threads

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); 
     ... 
    } 
} 

der Code die angegebene Anzahl von Threads erzeugt, die jeweils einen beginnt, und weist jeden Thread ein zufälliges device_id. Aus irgendeinem Grund haben die ersten zwei Threads, die erstellt werden, oft die gleichen device_id. Ich kann nicht herausfinden, warum das passiert.

+0

Dies ist statistisch korrekt, als ob Sie zwei Würfel werfen sie dich irgendwann geben die gleiche Anzahl plus Zufall ist nicht Thread-sicher - > http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx – dvhh

+3

@Mitch: Keine der verknüpften Fragen beschäftigen sich mit der gleichen Situation. Es ist nur die Thread-Sicherheit, die hier relevant ist, da es nur eine Instanz von Random gibt. –

+0

@Jon: Ja, das stimmt. –

Antwort

23

Random ist nicht Thread-sicher - Sie sollten nicht die gleiche Instanz von mehreren Threads verwenden. Es kann viel schlimmer kommen als nur die gleichen Daten zurück zu geben - indem Sie es aus mehreren Threads verwenden, können Sie es in einem Zustand "stecken", in dem es immer zurückgeben 0, IIRC.

Offensichtlich Sie wollen nicht nur eine neue Instanz für jeden Thread erstellen ungefähr zur gleichen Zeit, da sie mit den gleichen Samen am Ende dann ...

Ich habe ein article, das in dem geht Details davon und stellt eine Implementierung bereit, die eine Instanz von Random pro Thread unter Verwendung eines inkrementierenden Seeds instanziiert.

+0

Ich vermutete so viel, war mir aber nicht sicher, nachdem ich MSDN überprüft hatte. Ich überprüfe auch deinen Artikel. Vielen Dank. – dandan78

+0

Siehe auch Jon Skeets [MiscUtil.StaticRandom] (http://www.yoda.arachsys.com/csharp/miscutil/). – Brian

4

Random ist ein Pseudozufallszahlengenerator und es gibt nichts, das verhindert, dass dasselbe Ergebnis für mehrere Aufrufe zurückgegeben wird. Immerhin besteht eine Wahrscheinlichkeit dafür. Nicht zu erwähnen, dass gemäß der documentation:

Alle Instanzmitglieder sind nicht garantiert, Thread sicher sein.

So sollten Sie die Next Methode überhaupt nicht von mehreren Threads aufrufen.

1

Ihr Beispielcode zeigt nur eine Verwendung von _Random pro Thread. Angenommen, dies ist der Fall, können Sie auch die Zufallszahl in der Hauptschleife for generieren und die Zufallszahl in jeden Thread als Parameter übergeben.

for (int i = 0; i < no_threads; ++i) 
{ 
     var thread = new Thread(new ThreadStart(Send)); 
     thread.Start(_Random.Next(999999)); 
} 

und dann Thread-Funktion ändern Sie die Parameter akzeptieren:

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