java - ¿Cómo garantizar la seguridad de subprocesos del método estático de utilidad?
oop thread-safety (5)
Es bien sabido que los métodos estáticos con objetos inmutables como parámetros son seguros para subprocesos y los objetos mutables no lo son.
Yo contestaría esto. Los argumentos pasados a un método se almacenan en una pila, que es un idioma por hilo.
Si su parámetro es un objeto mutable, como una Date
, debe asegurarse de que otros subprocesos no lo están modificando al mismo tiempo en otro lugar. Pero esa es una cuestión diferente no relacionada con la seguridad de los hilos de su método.
El método que has publicado es seguro para subprocesos. No mantiene ningún estado y opera solo sobre sus argumentos.
Le recomendaría encarecidamente que lea Java Concurrencia en la práctica , o un libro similar dedicado a la seguridad de subprocesos en Java. Es un tema complejo que no se puede abordar adecuadamente a través de algunas respuestas de StackOverflow.
¿Existe alguna forma general o salida de reglas mediante la cual podamos garantizar la seguridad de subprocesos de los métodos estáticos utilizados específicamente en diversas clases de utilidad de cualquier aplicación? Aquí quiero señalar específicamente la seguridad del hilo de las aplicaciones web.
Es bien sabido que los métodos estáticos con Objetos inmutables como parámetros son seguros para subprocesos y los Objetos mutables no.
Si tengo un método de utilidad para alguna manipulación de java.util.Date
y ese método acepta una instancia de java.util.Date
, entonces este método no sería seguro para subprocesos. Entonces, ¿cómo hacer que el hilo sea seguro sin cambiar la forma de pasar los parámetros?
public class DateUtils {
public static Date getNormalizeDate(Date date) {
// some operations
}
}
También es la clase javax.faces.context.FacesContext
mutable? ¿Es seguro para subprocesos pasar una instancia de esta clase a dicho método de utilidad estática?
Esta lista de clases, instancias de las cuales pueden ser o no pasarse como parámetros, podría ser larga; Entonces, ¿qué puntos debemos tener en cuenta al escribir códigos de tales clases de utilidad?
Así es como lo pienso: imagine un CampSite (ese es un método estático). Como un campista, puedo traer un montón de objetos en mi mochila (eso es argumentos pasados en la pila). El CampSite me proporciona un lugar para colocar mi tienda de campaña y mi campada, etc., pero si lo único que el CampSite hace es permitirme modificar mis propios objetos, entonces es seguro para hilos. CampSite puede incluso crear cosas de la nada ( FirePit firepit = new FirePit();
), que también se crean en la pila.
En cualquier momento puedo desaparecer con todos mis objetos en mi mochila y puede aparecer uno de los otros campistas, haciendo exactamente lo que estaban haciendo la última vez que desaparecieron. Diferentes subprocesos en este CampSite no tendrán acceso a los objetos en la pila creada CampSite en otros subprocesos.
Digamos que solo hay un campStove (un solo objeto de CampStove, no instancias separadas). Si por un poco de imaginación estoy compartiendo un objeto CampStove, hay consideraciones de subprocesos múltiples. No quiero encender mi CampStove, desaparecer y luego reaparecer después de que otro campista lo haya apagado. Siempre estaría revisando si mi perro caliente había terminado y nunca lo haría. Tendría que poner algo de sincronización en algún lugar ... en la clase CampStove, en el método que se llamaba CampSite o en el propio CampSite ... pero como dice Duncan Jones , "eso es un asunto diferente".
Tenga en cuenta que incluso si estuviéramos acampando en instancias separadas de objetos CampSite no estáticos, compartir un campStove tendría las mismas consideraciones de subprocesos múltiples.
Como su clase no tiene ninguna variable miembro, su método no tiene estado (solo usa las variables locales y el argumento) y, por lo tanto, es seguro para subprocesos.
El código que lo llama podría no ser seguro para subprocesos, pero eso es otra discusión. Por ejemplo, la fecha no es segura para la cadena, si el código de llamada lee una fecha que ha sido escrita por otra cadena, debe usar la sincronización correcta en el código de escritura y lectura de la fecha.
Dada la estructura de la JVM, las variables locales, los parámetros del método y los valores de retorno son inherentemente "seguros para subprocesos". Pero las variables de instancia y las variables de clase solo serán seguras para subprocesos si diseñas tu clase adecuadamente. más here
Recomendaría crear una copia de ese objeto (mutable) tan pronto como se inicie el método y usar la copia en lugar del parámetro original.
Algo como esto
public static Date getNormalizeDate(Date date) {
Date input = new Date(date.getTime());
// ...
}