works thread statement sincronizacion sentencia semaforos programacion programa multihilos metodos metodo method juegos how hilos examples example con java java-8 synchronized default-method jsr335

thread - synchronized statement in java



¿Cuál es la razón por la que no se permite la "sincronización" en los métodos de interfaz de Java 8? (1)

Esta fue una decisión deliberada, en lugar de una omisión (como se sugirió en otra parte). Aunque al principio puede parecer obvio que uno querría apoyar el modificador synchronized en los métodos predeterminados, resulta que hacerlo sería peligroso, y así Estaba prohibido.

Los métodos sincronizados son una forma abreviada 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. Puede parecer sensato extender esta semántica a los métodos predeterminados también; después de todo, también son métodos de instancia con un receptor. (Tenga en cuenta que synchronized métodos synchronized son una optimización sintáctica en su totalidad; no son necesarios, son más compactos que el bloque synchronized correspondiente. Se puede argumentar 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 esa nave zarpó hace mucho tiempo.)

Entonces, ¿por qué son peligrosos? La sincronización es sobre el bloqueo. El bloqueo se trata de coordinar el acceso compartido al estado mutable. Cada objeto debe tener una política de sincronización que determine qué bloqueos guardan qué variables de estado. (Ver Concurrencia de Java en la práctica , sección 2.4.)

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

Es la clase que posee el estado que llega a determinar la política de sincronización de ese objeto. Pero las interfaces no poseen el estado de los objetos en los que se mezclan. Por lo tanto, el uso de un método sincronizado en una interfaz asume una política de sincronización particular, pero no tiene una base razonable para suponer, por lo que podría ser el caso el uso de la sincronización no proporciona seguridad de subprocesos adicionales en absoluto (es posible que esté sincronizando en el bloqueo incorrecto). Esto le dará la falsa sensación de confianza de que ha hecho algo con respecto a la seguridad de los subprocesos, y ningún mensaje de error le indicará que está asumiendo una política de sincronización incorrecta.

Ya es lo suficientemente difícil mantener de manera consistente una política de sincronización para un archivo fuente único; es aún más difícil asegurar que una subclase se adhiera correctamente a la política de sincronización definida por su superclase. Tratar de hacerlo entre clases tan débilmente acopladas (una interfaz y posiblemente las muchas clases que lo implementan) sería casi imposible y altamente propenso a errores.

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

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étodos:

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 las implementaciones default no deben hacer suposiciones sobre el estado de implementación concreta, o que una palabra clave de este tipo simplemente no haría valer su peso.

Pregunta:

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