Cada vez que lo haces new Random()
se inicializa usando el reloj. Esto significa que en un ciclo cerrado obtienes el mismo valor muchas veces. Debe mantener una única instancia aleatoria y seguir usando Siguiente en la misma instancia.
//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);
}
}
Editar (ver comentarios): ¿por qué necesitamos un lock
aquí?
Básicamente, Next
va a cambiar el estado interno de la Random
instancia. Si hacemos eso al mismo tiempo desde múltiples hilos, podría argumentar "acabamos de hacer que el resultado sea aún más aleatorio", pero lo que realmente estamos haciendo es potencialmente romper la implementación interna, y también podríamos comenzar a obtener los mismos números de diferentes hilos, lo que podría ser un problema, y podría no serlo. Sin embargo, la garantía de lo que sucede internamente es el problema más importante; ya Random
que no garantiza la seguridad del hilo. Por lo tanto, hay dos enfoques válidos:
- Sincronice para que no accedamos al mismo tiempo desde diferentes hilos
- Use diferentes
Random
instancias por hilo
Cualquiera puede estar bien; pero eliminar una sola instancia de varias personas que llaman al mismo tiempo solo es un problema.
El lock
logra el primero (y más simple) de estos enfoques; Sin embargo, otro enfoque podría ser:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
esto es por subproceso, por lo que no necesita sincronizar.
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
no produce mejores números "aleatorios" que.Next(0, 256)