Toda vez que você faz new Random()
isso é inicializado usando o relógio. Isso significa que, em um circuito fechado, você obtém o mesmo valor várias vezes. Você deve manter uma única instância aleatória e continuar usando Next na mesma instância.
//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 comentários): por que precisamos de um lock
aqui?
Basicamente, Next
vai mudar o estado interno da Random
instância. Se fizermos isso ao mesmo tempo a partir de vários encadeamentos, você poderá argumentar "acabamos de tornar o resultado ainda mais aleatório", mas o que realmente estamos fazendo é potencialmente violar a implementação interna e também podemos começar a obter os mesmos números de threads diferentes, o que pode ser um problema - e talvez não. A garantia do que acontece internamente é o problema maior; desde Random
que não faça nenhuma garantia de segurança de linha. Portanto, existem duas abordagens válidas:
- Sincronize para não acessá-lo ao mesmo tempo a partir de threads diferentes
- Use
Random
instâncias diferentes por thread
Qualquer um pode ficar bem; mas mutex uma instância única de vários chamadores ao mesmo tempo está apenas causando problemas.
O lock
atinge a primeira (e mais simples) dessas abordagens; no entanto, outra abordagem pode ser:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
isso é por thread, para que você não precise sincronizar.
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
não deu qualquer melhores números "aleatórios" que.Next(0, 256)