Saltar al contenido

Equivalencia funcional en Java

Este post ha sido aprobado por expertos así se asegura la exactitud de nuestra esta división.

Solución:

Entonces, ¿es siempre seguro crear un static ¿Objeto final de cualquier clase a la que apunta si no tiene campos?

Me atrevería a decir que sí. Al no tener campos, una clase no tiene estado y, por lo tanto, es inmutable, lo que siempre es deseable en un entorno de subprocesos múltiples.

Los objetos sin estado siempre son seguros para subprocesos.

Los objetos inmutables siempre son seguros para subprocesos.

Un extracto de Java Concurrency In Practice:

Dado que las acciones de un subproceso que accede a un objeto sin estado no pueden afectar la corrección de las operaciones en otros subprocesos, los objetos sin estado son seguros para subprocesos.

Los objetos sin estado siempre son seguros para subprocesos.

El hecho de que la mayoría de los servlets se puedan implementar sin estado reduce en gran medida la carga de hacer que los servlets sean seguros para subprocesos. Solo cuando los servlets quieren recordar cosas de una solicitud a otra, el requisito de seguridad de subprocesos se convierte en un problema.

Un objeto inmutable es aquel cuyo estado no se puede cambiar después de la construcción. Los objetos inmutables son inherentemente seguros para subprocesos; sus invariantes las establece el constructor, y si su estado no se puede cambiar, estas invariantes siempre se mantienen.

Los objetos inmutables siempre son seguros para subprocesos.

Los objetos inmutables son simples. Solo pueden estar en un estado, que es cuidadosamente controlado por el constructor. Uno de los elementos más difíciles del diseño de programas es razonar sobre los posibles estados de objetos complejos. Razonar sobre el estado de los objetos inmutables, por otro lado, es trivial.


¿No causaría esto un problema de subprocesos múltiples cuando se llama a compare desde dos subprocesos en paralelo?

No. Cada subproceso tiene su propia pila donde se almacenan las variables locales (incluidos los parámetros del método). La pila del subproceso no se comparte, por lo que no hay forma de estropearlo en paralelo.

Otro buen ejemplo sería un servlet sin estado. Un extracto más de ese gran libro.

@ThreadSafe
public class StatelessFactorizer implements Servlet 
    public void service(ServletRequest req, ServletResponse resp) 
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        encodeIntoResponse(resp, factors);
    

StatelessFactorizer es, como la mayoría de los servlets, sin estado: no tiene campos y no hace referencia a campos de otras clases. El estado transitorio para un cálculo particular existe únicamente en las variables locales que se almacenan en la pila del subproceso y son accesibles solo para el subproceso en ejecución. Un hilo accediendo a un StatelessFactorizer no puede influir en el resultado de otro hilo accediendo al mismo StatelessFactorizer; porque los dos hilos no comparten estadoes como si estuvieran accediendo a distintas instancias.


¿Es como si cada subproceso tuviera autonomía de ejecución si no se comparten campos?

Cada subproceso tiene su propio contador de programa, pila y variables locales. Existe un término “confinamiento de subprocesos” y una de sus formas se llama “confinamiento de pila”.

El confinamiento de pila es un caso especial de confinamiento de subprocesos en el que solo se puede acceder a un objeto a través de variables locales. Así como la encapsulación puede facilitar la conservación de invariantes, las variables locales pueden facilitar el confinamiento de objetos en un subproceso. Las variables locales están intrínsecamente confinadas al hilo de ejecución; existen en la pila del subproceso en ejecución, que no es accesible para otros subprocesos.

Leer:

  • Concurrencia de Java en la práctica
  • Confinamiento de hilos
  • Confinamiento de pila usando referencia de objeto local

Los problemas de subprocesos múltiples son causados ​​por cambios de estado. Si no hay un estado que se cambie, no hay tales problemas. Esa es también la razón por la cual los objetos inmutables son muy convenientes en un entorno de subprocesos múltiples.

En este caso particular, el método solo opera en los parámetros de entrada s1 y s2 y no se mantiene ningún estado.

Por lo que es siempre seguro para crear un static final Object de cualquier clase a la que apunte si no tiene campos?

“Siempre” es una afirmación demasiado fuerte. Es fácil construir una clase artificial donde las instancias no son seguras para subprocesos a pesar de no tener campos:

public class NotThreadSafe 
    private static final class MapHolder 
        private static final Map map =
            // use ConcurrentHashMap so that different instances don't
            // interfere with each other:
            new ConcurrentHashMap<>();
    

    private StringBuilder getMyStringBuilder() 
        return MapHolder.map.computeIfAbsent(this, k -> new StringBuilder());
    

    public void append(final Object s) 
        getMyStringBuilder().append(s);
    

    public String get() 
        return getMyStringBuilder().toString();
    

. . . pero ese código no es realista. Si sus instancias no tienen ningún estado mutable, naturalmente serán seguras para subprocesos; y en normal Código Java, estado mutable significa campos de instancia.

Reseñas y puntuaciones

Tienes la opción de añadir valor a nuestro contenido informacional cooperando tu veteranía en las explicaciones.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *