Jedes Mal, wenn Sie dies tun, wird new Random()
es mit der Uhr initialisiert. Dies bedeutet, dass Sie in einer engen Schleife oft den gleichen Wert erhalten. Sie sollten eine einzelne Zufallsinstanz beibehalten und Next auf derselben Instanz verwenden.
//Function to get a random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}
Bearbeiten (siehe Kommentare): Warum brauchen wir lock
hier ein?
Grundsätzlich Next
wird sich der interne Status der Random
Instanz ändern . Wenn wir dies gleichzeitig aus mehreren Threads heraus tun, könnten Sie argumentieren, "wir haben das Ergebnis nur noch zufälliger gemacht", aber was wir tatsächlich tun, ist möglicherweise, die interne Implementierung zu brechen, und wir könnten auch anfangen, die gleichen Zahlen zu erhalten von verschiedenen Threads, die möglicherweise ein Problem sein - und vielleicht nicht. Die Garantie dafür, was intern passiert, ist jedoch das größere Problem. da Random
sich nicht machen keine Garantien für Thread-Sicherheit. Somit gibt es zwei gültige Ansätze:
- Synchronisieren Sie, damit wir nicht gleichzeitig von verschiedenen Threads darauf zugreifen
- Verwenden Sie unterschiedliche
Random
Instanzen pro Thread
Beides kann in Ordnung sein; Das Stummschalten einer einzelnen Instanz von mehreren Anrufern gleichzeitig ist jedoch nur ein Problem .
Das lock
erreicht den ersten (und einfacheren) dieser Ansätze; Ein anderer Ansatz könnte jedoch sein:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
Dies ist dann pro Thread, sodass Sie nicht synchronisieren müssen.
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
ergibt keine besseren "Zufallszahlen" als.Next(0, 256)