¿Cuál es la razón por la que "sincronizado" no está permitido en los métodos de interfaz de Java 8?


En Java 8, puedo escribir fácilmente:

interface Interface1 {
    default void method1() {
        synchronized (this) {
            // Something
        }
    }

    static void method2() {
        synchronized (Interface1.class) {
            // Something
        }
    }
}

Obtendré la semántica de sincronización completa que puedo usar también en las clases. Sin embargo, no puedo usar el modificador synchronized en las declaraciones de método:

interface Interface2 {
    default synchronized void method1() {
        //  ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
    }

    static synchronized void method2() {
        // ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
    }
}

Ahora, se puede argumentar que las dos interfaces se comportan de la misma manera, excepto que Interface2 establece un contrato en method1() y en method2(), que es un poco más fuerte que lo que hace Interface1. Por supuesto, también podríamos argumentar que default las implementaciones no deben hacer ninguna suposición sobre el estado de implementación concreta, o que tal palabra clave simplemente no tiraría de su peso.

Pregunta:

¿Cuál es la razón por la que el grupo de expertos JSR-335 decidió no apoyar synchronized en los métodos de interfaz?

Author: Tim Castelijns, 2014-05-04

1 answers

Esta fue una decisión deliberada, más que una omisión (como se ha sugerido en otros lugares. Si bien al principio puede parecer obvio que uno querría soportar el modificador synchronized en los métodos predeterminados, resulta que hacerlo sería peligroso, y por lo tanto estaba prohibido.

Los métodos sincronizados son una abreviatura de un método que se comporta como si todo el cuerpo estuviera encerrado en un bloque synchronized cuyo objeto de bloqueo es el receptor. Podría parecer sensato extender esta semántica al valor predeterminado métodos también; después de todo, son métodos de instancia con un receptor también. (Tenga en cuenta que los métodos synchronized son completamente una optimización sintáctica; no son necesarios, solo son más compactos que el bloque synchronized correspondiente. Hay un argumento razonable para ser hecho de que esta fue una optimización sintáctica prematura en primer lugar, y que los métodos sincronizados causan más problemas de los que resuelven, pero ese barco zarpó hace mucho tiempo.)

Entonces, ¿por qué son peligrosos? Sincronización se trata de bloquear. El bloqueo se trata de coordinar el acceso compartido al estado mutable. Cada objeto debe tener una directiva de sincronización que determine qué bloqueos protegen qué variables de estado. (Véase Java Concurrency in Practice, sección 2.4.)

Muchos objetos utilizan como política de sincronización el Patrón de Monitor de Java (JCiP 4.1), en el que el estado de un objeto está protegido por su bloqueo intrínseco. No hay nada mágico o especial en este patrón, pero es conveniente, y el uso de la palabra clave synchronized en métodos implícitamente asume este patrón.

Es la clase que posee el estado la que determina la política de sincronización de ese objeto. Pero las interfaces no poseen el estado de los objetos en los que se mezclan. Así que, usando un método sincronizado en una interfaz asume una particular política de sincronización, pero que no tienen ninguna base razonable para asumir, por lo que bien podría ser el caso de que el uso de la sincronización no proporciona seguridad adicional del hilo en absoluto (es posible que esté sincronizando en el bloqueo incorrecto). Esto le daría la falsa sensación de confianza de que ha hecho algo sobre la seguridad del hilo, y ningún mensaje de error le indica que está asumiendo la política de sincronización incorrecta.

Ya es bastante difícil mantener consistentemente una política de sincronización para un solo archivo de origen; es aún más difícil asegurarse de que una subclase se adhiera correctamente a la política de sincronización definida por su superclase. Tratar de hacerlo entre tales clases poco acopladas (una interfaz y las posiblemente muchas clases que la implementan) sería casi imposible y altamente propenso a errores.

Dados todos esos argumentos en contra, ¿cuál sería el argumento a favor? Parece que se trata principalmente de hacer que las interfaces se comporten más como rasgos. Si bien este es un deseo comprensible, el centro de diseño para los métodos predeterminados es la evolución de la interfaz, no "Rasgos Traits". Donde los dos podrían ser consistentemente logrado, nos esforzamos por hacerlo, pero cuando uno está en conflicto con el otro, tuvimos que elegir a favor del objetivo principal de diseño.

 246
Author: Brian Goetz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-26 20:09:35