El título lo resume bastante bien: podemos crear una instancia de java.util.Random (o SecureRandom) y usarla cada vez que necesitemos un valor aleatorio o podemos crear una nueva instancia cada vez que lo solicitemos. ¿Se pregunta cuál es la forma preferida y por qué?

Para dar una idea sobre el contexto: el valor aleatorio se genera dentro de un controlador de solicitud HTTP, uno por solicitud, y estoy buscando la mejor combinación de seguridad y rendimiento considerando multi-threading.

7
khachik 16 oct. 2018 a las 18:03

2 respuestas

La mejor respuesta

Depende.

La creación de una sola instancia es obviamente más simple y debería ser el comportamiento predeterminado. Tanto Random como SecureRandom son seguras para subprocesos y, por lo tanto, funcionarán bien. Primero haga lo simple y correcto que funcione, luego mida su desempeño con su presupuesto de contención / rendimiento máximo esperado y analice los resultados.

Random

Si está usando Random y el enfoque de instancia única es demasiado lento, considere usar ThreadLocalRandom si es posible. El JavaDoc en Random sugiere su uso muy bien:

Las instancias de java.util.Random son seguras para subprocesos. Sin embargo, el uso simultáneo de la misma instancia de java.util.Random en varios subprocesos puede generar contención y, en consecuencia, un rendimiento deficiente. En su lugar, considere usar ThreadLocalRandom en diseños multiproceso.

Solo creará una instancia para cada hilo que acceda a él. El costo de creación de una instancia Random / ThreadLocalRandom no es una locura, pero es más alto que la creación de un objeto "normal", por lo que probablemente deberías evitar crear una nueva instancia para cada solicitud entrante. Crear uno por hilo es generalmente un buen punto ideal.

Yo diría que en las aplicaciones modernas con subprocesos agrupados, casi siempre debería usar ThreadLocalRandom en lugar de Random; la aleatoriedad es la misma, pero el rendimiento de un solo subproceso es mucho mejor.

SecureRandom

Sin embargo, si está usando SecureRandom, ThreadLocalRandom no es una opción. De nuevo, no adivines, mide! Quizás usar una sola instancia compartida de un SecureRandom sea lo suficientemente bueno. Pruebe con el pico de contención esperado y, si la instancia aleatoria segura resulta ser un cuello de botella, solo entonces piense en formas de mejorar la situación.

Crear una instancia de SecureRandom es muy costoso, por lo que no desea crear una para cada solicitud entrante.

Dependiendo de su aplicación, una ThreadLocal<SecureRandom> puede ser una opción. Aún así, creo que es una exageración y un esquema similar al Striped (con X SecureRandom instancias creadas y a las que se accede de forma aleatoria para ayudar a evitar la contención).

5
Petr Janeček 16 oct. 2018 a las 15:41

Si necesita números aleatorios para la seguridad de la información, solo un RNG criptográfico (como java.security.SecureRandom) será suficiente. Y para cualquier RNG criptográfico, el enfoque más simple es usar solo una instancia segura para subprocesos para que la use toda la aplicación (tenga en cuenta que SecureRandom es seguro para subprocesos según la documentación); Por lo general, no hay ningún beneficio en la creación de varias instancias de un RNG criptográfico, ya que eventualmente todas tendrán que inicializarse con datos de alta entropía ("impredecibles").

La recopilación de estos datos "impredecibles" no es trivial y, al menos para tu aplicación, no necesita preocuparse por eso cuando use SecureRandom, que en gran medida hace esto por usted e incluye un método setSeed que puede usar para agregar datos adicionales para complementar su aleatoriedad.

2
Peter O. 19 oct. 2018 a las 02:59