poo - interfaces en java ejercicios resueltos
¿Por qué no se puede sincronizar un método abstracto? (4)
Estaba leyendo un hilo de CodeRanch que decía que los métodos abstractos no podían sincronizarse debido al hecho de que una clase abstracta no puede ser instanciada, lo que significa que no hay objetos que bloquear.
Esto no tiene sentido ya que una clase abstracta es una definición (contrato) para una clase secundaria. La definición abstracta de un método sincronizado no necesita bloquearse, el niño sí lo hace. Todo el encabezado abstracto indicaría es que el niño debe sincronizar este método. ¿Mi lógica en esto es correcta? Si no puede alguien explicar por qué estoy equivocado?
Creo que una lógica detrás de eso podría ser si la clase implementadora debe decidir si sincronizar o no ese método. Es decir, le da la libertad al implementador para elegir si desea proporcionar una implementación sincronizada o no sincronizada. Además, el cliente también tendría la opción de seleccionar la versión no sincronizada para evitar la sobrecarga de sincronización si la seguridad de subprocesos no es un problema.
Lo siento, no tiene sentido, así es como funciona. El comportamiento de bloqueo no se puede especificar mediante métodos abstractos o métodos de interfaz, no es parte del contrato. Probablemente, la idea era que el comportamiento de bloqueo es fundamentalmente parte de la implementación (las diferentes implementaciones querrán realizar el bloqueo de manera diferente) y sería demasiado difícil especificarlo en ese nivel de abstracción.
El comentario sobre no poder instanciar la clase abstracta es basura. Dado que tiene que ser un método de instancia para ser abstracto, ciertamente hay una referencia que podría estar bloqueada. Los métodos concretos en clases abstractas todavía pueden referirse a this
. Sin embargo, eso todavía no significa que las clases abstractas deban poder sincronizarse.
Si un método está o no sincronizado es un detalle de implementación del método. La sincronización no se especifica en ninguna parte como un contrato declarativo, tampoco es que se pueda sincronizar en las interfaces.
La forma en que una clase implementa las garantías de seguridad de subprocesos que proporciona depende de ello. Si una clase abstracta desea imponer un enfoque particular, debe usar el patrón de método de plantilla:
// I hate synchronizing on "this"
private final Object lock = new Object();
public final void foo() {
synchronized(lock) {
fooImpl();
}
}
protected abstract void fooImpl();
Sin embargo, eso es bastante peligroso en sí mismo, dado que efectivamente está llamando a un código "desconocido" dentro de un bloqueo, que es una receta para puntos muertos, etc.
synchronized void foo()
{
body
}
se define como equivalente a
void foo()
{
synchronized(this)
{
body
}
}
(si estático, sincronizado en la clase en lugar de this
)
Dado que un método abstracto no tiene cuerpo, synchronized
palabra clave synchronized
en el método no está definida.