2010-06-17 16 views
5

Estoy luchando con una decisión. Estoy escribiendo una biblioteca/API segura para subprocesos. Los oyentes pueden registrarse, por lo que se notifica al cliente cuando sucede algo interesante. ¿Cuál de las dos implementaciones es la más común?notificar oyente dentro o fuera de la sincronización interna

class MyModule { 
    protected Listener listener; 

    protected void somethingHappens() { 
     synchronized(this) { 
      ... do useful stuff ... 
      listener.notify(); 
     } 
    } 
} 

o

class MyModule { 
    protected Listener listener; 

    protected void somethingHappens() { 
     Listener l = null; 

     synchronized(this) { 
      ... do useful stuff ... 
      l = listener; 
     } 
     l.notify(); 
    } 
} 

En la primera aplicación, el oyente se notifica dentro de la sincronización. En la segunda implementación, esto se hace fuera de la sincronización.

Creo que el segundo es aconsejable, ya que deja menos espacio para bloqueos potenciales. Pero estoy teniendo problemas para convencerme a mí mismo.

Una desventaja de la segunda imlementación es que el cliente puede recibir notificaciones 'incorrectas', lo que sucede si accede y cambia el módulo antes de la instrucción l.notify(). Por ejemplo, si le pide al módulo que deje de enviar notificaciones, esta notificación se envía de todos modos. Este no es el caso en la primera implementación.

muchas gracias

Respuesta

1

Depende de dónde usted está recibiendo oyente en su método, la cantidad de oyentes que tiene, cómo se suscribe al oyente/cancela la suscripción

Asumiendo de su ejemplo, que tienen un solo oyente a continuación, Es posible que sea mejor utilizar secciones críticas (o monitores) para diferentes partes de la clase en lugar de bloquear todo el objeto.

Puede tener un bloqueo para realizar tareas dentro del método que sean específicas del objeto/tarea en cuestión, y otro para el oyente suscribirse/cancelar/notificar (esto es para asegurar que el oyente no se cambie durante una notificación)

También me gustaría utilizar un ReadWriteLock que le protege referencias oyente (ya sea solo o una lista de oyentes)

Responder a usted comenta:

Creo que debe notificar al oyente que haya desbloqueado la clase. Esto se debe a que el resultado de esa notificación podría dar como resultado un hilo diferente al tratar de obtener acceso a la clase, lo que podría no ser capaz, bajo ciertas circunstancias, de llevar a un punto muerto.

Notificar a un oyente (si está protegido como he descrito) no debe contener ningún otro hilo que requiera las instalaciones de la clase. La mejor estrategia es crear bloqueos que sean específicos del estado de la clase y bloqueos específicos de la notificación segura.

Si toma su ejemplo de suspensión de notificaciones, esto podría estar cubierto por el bloqueo que rige las notificaciones, por lo que si un hilo diferente 'suspende' las notificaciones, se procesará la suspensión o se completará la notificación actual, si el otro hilo suspende la notificación entre la tarea que se está procesando y la notificación que se está produciendo, l.notify() no sucederá.

Listener l = null; 

synchronised(processLock_) { 
    ... do stuff.... 
    synchronised(notifyLock_) { 
     l = listener; 
    } 
} 
// 
// current thread preempted by other thread that suspends notification here. 
// 

synchronised(notifyLock_) { // ideally use a readwritelock here... 
    l = allowNotify_ ? l: null; 
} 
if(l) 
    l.notify(); 
+0

Gracias por su respuesta. Intencionalmente no menciono la parte de suscripción/desuscripción. Quiero suponer que hay un oyente fijo. Mi pregunta es más bien si es aconsejable exponer la sincronización fuera de la clase o no. –

+0

@Jary Zeels, ver las adiciones a la respuesta –

+0

Gracias Adrian por su aclaración, lo entiendo ahora. La situación con un oyente es clara para mí. Voy a pensar en la situación en la que se pueden registrar más oyentes, porque entonces, la reincorporación puede ser un problema. No desea que los eventos se entreguen en el orden incorrecto cuando, por ejemplo, uno de los oyentes notificados hace algo que desencadena una nueva notificación. Lo pensaré y volveré con más preguntas si es necesario. Gracias de nuevo. –

Cuestiones relacionadas