¿Cómo te modificar el código para tener un proveedor de azar seguro para hilos sin la ayuda de ThreadLocal?
Jon responde a su pregunta en el artículo se ha vinculado a:
uso un caso, sino también el uso de una cerradura que cada persona que llama tiene que recordar para adquirir mientras se está utilizando el generador de números aleatorios. Eso se puede simplificar mediante el uso de un contenedor que hace el bloqueo por usted, pero en un sistema con varios subprocesos potencialmente perderá mucho tiempo esperando bloqueos.
Así que simplemente asegúrelo siempre en el envoltorio, y desbloquéelo cuando haya terminado.
Si eso es lo suficientemente barato, genial, es lo suficientemente barato.
Si eso no es lo suficientemente barato, entonces tiene dos opciones. Primero, hazlo más económico. En segundo lugar, escribe una implementación de seguridad de subprocesos de un generador de números pseudoaleatorios que se puede usar sin bloquear.
Hay varias maneras de hacerlo más barato. Por ejemplo, puedes intercambiar espacio por tiempo; podría generar una matriz de cien mil números aleatorios cuando se inicie el programa, y luego escribir un algoritmo sin bloqueo que ofrezca valores aleatorios calculados previamente de la matriz. Cuando se quede sin valores, genere otros cien mil valores en una matriz y cambie la nueva matriz por la anterior.
Tiene la desventaja de que su consumo de memoria es aproximadamente cien mil veces mayor de lo que podría ser, y que cada cien mil números de repente se vuelve muy lento y luego se acelera de nuevo. Si eso no es aceptable, entonces presenta una estrategia que es aceptable. Tú eres el único que sabe cuál es el rendimiento aceptable y el que no.
O, como dije, escriba la suya propia si no le gusta la que se le proporciona. Escriba una implementación de ejecución aleatoria de Random con un rendimiento aceptable y utilícela desde varios hilos.
¡Vi lo que dijo Jon sobre encerrar el envoltorio pero no estoy seguro de cómo se vería el código!
Algo así como:
sealed class SafeRandom
{
private Random random = new Random();
public int Next()
{
lock(random)
{
return random.Next();
}
}
}
Ahora, cada vez que llame a continuación, se obtiene un bloqueo. (Siempre bloquee un objeto privado ; de esa manera usted sabe que su código es el único código que lo bloquea!) Si dos hilos llaman "al mismo tiempo" a continuación, el "perdedor" bloquea hasta que el "ganador" se va el siguiente método.
Si quería, incluso se podría hacer que el objeto SafeRandom una clase estática:
static class SafeRandom
{
private static Random random = new Random();
public static int Next()
{
lock(random)
{
return random.Next();
}
}
}
y ahora se puede llamar SafeRandom.Next() desde cualquier hilo.
También hay un seguimiento en el artículo: https://msmvps.com/blogs/jon_skeet/archive/2009/11/04/revisiting-randomness.aspx donde explica otras estrategias de seguridad de hilos. – CodesInChaos