2010-06-17 3 views
5

Sono in difficoltà con una decisione. Sto scrivendo una libreria/API thread-safe. Gli ascoltatori possono essere registrati, quindi il client viene avvisato quando succede qualcosa di interessante. Quale delle due implementazioni è più comune?notificare l'ascoltatore all'interno o all'esterno della sincronizzazione 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(); 
    } 
} 

Nella prima realizzazione, l'ascoltatore è notificato all'interno della sincronizzazione. Nella seconda implementazione, questa operazione viene eseguita al di fuori della sincronizzazione.

Ritengo che la seconda sia consigliata, in quanto rende meno spazio a potenziali blocchi. Ma sto avendo problemi a convincere me stesso.

Uno svantaggio della seconda implementazione è che il client potrebbe ricevere notifiche "errate", il che accade se ha effettuato l'accesso e modificato il modulo prima dell'istruzione l.notify(). Ad esempio, se ha chiesto al modulo di interrompere l'invio di notifiche, questo notificaiton viene comunque inviato. Questo non è il caso della prima implementazione.

grazie mille

risposta

1

Dipende da dove hai trovato ascoltatore nel metodo, quanti ascoltatori che hai, come l'ascoltatore sottoscrive/unsubscribes

Supponendo dal vostro esempio, avete un solo ascoltatore poi potrebbe essere preferibile utilizzare sezioni critiche (o monitor) per parti diverse della classe anziché bloccare l'intero oggetto.

È possibile avere un blocco per l'esecuzione di attività all'interno del metodo specifico per l'oggetto/attività in questione e uno per il listener sottoscrizione/annullamento sottoscrizione/notifica (per garantire che il listener non venga modificato durante una notifica).

Vorrei anche utilizzare un ReadWriteLock proteggere voi riferimenti ascoltatore (singole o elenco di ascoltatori)

Rispondere si commento:

Penso che si dovrebbe avvisare l'ascoltatore dopo aver sbloccato la classe. Questo perché, il risultato di tale notifica potrebbe comportare un thread diverso che tenta di accedere alla classe, che potrebbe non essere in grado di fare, in determinate circostanze, portando a deadlock.

La notifica a un ascoltatore (se protetta come ho descritto) non deve contenere nessun altro thread che richiede le funzionalità della classe. La strategia migliore consiste nel creare blocchi specifici per lo stato della classe e blocchi specifici per la notifica sicura.

Se prendete il vostro esempio di notifiche sospensione, questo potrebbe essere coperto dalla serratura che governa le notifiche, quindi se le notifiche un thread diverso 'sospende', sia l'sospendere verranno trattati o la notifica corrente completa, se l'altro thread sospende la notifica tra l'attività in elaborazione e la notifica che si verifica, il l.notify() non si verificherà.

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

Grazie per la risposta. Intendo intenzionalmente non menzionare la parte di iscrizione/annullamento dell'iscrizione. Voglio supporre che ci sia un ascoltatore fisso. La mia domanda è piuttosto se è saggio esporre la sincronizzazione al di fuori della classe o meno. –

+0

@Jary Zeels, vedere le aggiunte per rispondere allo –

+0

Grazie Adrian per il chiarimento, lo capisco ora. La situazione con un ascoltatore mi è chiara. Penserò alla situazione in cui possono essere registrati più ascoltatori, perché in tal caso il re-entrancycan può essere un problema. Non si desidera che gli eventi vengano recapitati nell'ordine sbagliato quando, per esempio, uno degli ascoltatori notificati fa qualcosa che attiva una nuova notifica. Ci penserò e tornerò con altre domande se necessario. Grazie ancora. –

Problemi correlati