2013-10-09 7 views
32

Ok. Hier ist, was ich weiß, dass nicht funktionieren:Korrekte Art, Random in Multithread-Anwendung zu verwenden

int Rand() 
{ 
    //will return the same number over and over again 
    return new Random().Next(); 
} 

static Random rnd=new Random(); 

int Rand() 
{ 
    //if used like this from multiple threads, rnd will dissintegrate 
    //over time and always return 0 
    return rnd.Next(); 
} 

Diese korrekt funktionieren, aber wenn von mehreren Threads verwendet wird, geht die CPU-Auslastung Weg nach oben, die ich nicht will, und was ich denke, ist nicht notwendig:

int Rand() 
{ 
    lock(rnd) 
    { 
     return rnd.Next(); 
    } 
} 

Also, gibt es eine Thread-safe Random-Klasse für C#, oder eine bessere Möglichkeit, es zu verwenden?

+2

Probieren Sie eine 'ThreadLocal '. 'private static readonly ThreadLocal rand = neu ThreadLocal (() => neu Random());' –

+7

@JeroenVannevel: Wahrscheinlich wollen Sie die Samen der 'Random'-Instanzen zufallsgenerieren, da sonst Threads zur gleichen Zeit starten würde die gleiche Folge von Zufallszahlen bekommen. – dtb

+0

.. und nehmen Sie eine globale gesperrte statische Zufallsinstanz für den Seed der zufälligen ThreadLocal-Instanzen. – Ralf

Antwort

45

ich so etwas wie dieses:

public static class StaticRandom 
{ 
    static int seed = Environment.TickCount; 

    static readonly ThreadLocal<Random> random = 
     new ThreadLocal<Random>(() => new Random(Interlocked.Increment(ref seed))); 

    public static int Rand() 
    { 
     return random.Value.Next(); 
    } 
} 
+0

Ich mag das wirklich, es funktioniert richtig, und wenn es in Multithread verwendet wird, ist dieses Beispiel 10 Mal schneller als die Lock-Methode! –

+0

Wird dieses Risiko nicht zu einem Bündel von Random-Instanzen mit demselben Seed führen, wenn Threads erstellt werden und ungefähr zur gleichen Zeit verwendet werden? –

+3

@EricJ. nein, weil es einen steigenden Samen verwendet. –

5

denke ich, was Sie wollen Threadstatic ist

[ThreadStatic] 
static Random rnd=new Random(); 

int Rand() 
{ 
    if (rnd == null) 
    { 
     rnd = new Random() 
    } 
    //Now each thread gets it's own version 
    return rnd.Next(); 
} 

Auf diese Weise jeder Thread seine eigene Version Ihrer rnd Eigenschaft erhalten

Der Grund Ihrer Schließanlage wird die CPU-Auslastung erhöhen, da alle Threads auf die warten einzelner Punkt (sollte nur ein Problem sein, wenn Sie es häufig verwenden)

[Update] Ich habe die Initialisierung behoben. Wie jemand darauf hingewiesen hat, lässt es die Tatsache zurück, dass, wenn Sie mehrere Threads in der gleichen Millisekunde starten, sie dieselben Ergebnisse produzieren werden.

+3

Laut dieser Antwort http://StackOverflow.com/a/18337158/1164966 ist 'ThreadLocal ' gegenüber '[ThreadStatic]' zu bevorzugen, da es garantiert, dass das Feld für jeden Thread initialisiert wird. –

+0

Oder wenn Sie ThreadStatic nicht mögen, dann erstellen Sie explizit so viele Random() - Instanzen wie Sie theads haben. – Eiver

+3

Es ist sowieso riskant. Wenn Sie zwei Threads in schneller Folge starten, können ihre Seeds die gleichen sein. – harold

12
readonly ThreadLocal<Random> random = 
    new ThreadLocal<Random>(() => new Random(GetSeed())); 

int Rand() 
{ 
    return random.Value.Next(); 
} 

static int GetSeed() 
{ 
    return Environment.TickCount * Thread.CurrentThread.ManagedThreadId; 
} 

(schamlos aus dem Kommentar von Jeroen Vannevel gestohlen)

+0

Ich habe keine Schande zu upvote, zuerst angekommen, zuerst serviert :) – AlexH

+2

Es gibt keine Schande, Vorschläge zu verbessern!;) –

+1

multipliziert Zeit mit Thread-ID ist albern. Betrachten Sie die Fälle, in denen einer von ihnen eine 0 oder auch nur eine Zweierpotenz ist. Und selbst wenn das kein Problem wäre, trifft das Erzeugen eines zufälligen 31-Bit-Samens für jede Instanz das Geburtstagsproblem noch schwerer als Alessandro. – CodesInChaos

1

Meine Gruppe vor kurzem in diese aussah. Wir kamen zu dem Schluss, dass wir einen Zufallszahlengenerator verwenden sollten, der speziell für die parallele Datenverarbeitung entwickelt wurde. Tina's Zufallszahlengenerator-Bibliothek (http://numbercrunch.de/trng/) hat eine stabile Implementierung und ein Handbuch mit einer theoretischen Einführung und Verweisen auf die relevante Literatur. Bis jetzt sind wir sehr zufrieden damit.

+1

betrifft dies C++, nicht C#, aber trotzdem nützlich –

Verwandte Themen