2013-04-06 12 views
10

Nel documento ufficiale Akka, si declinano:In che modo Akka implementa la relazione "prima-prima" di tipo JMM?

Per evitare problemi di visibilità e di riordino su attori, Akka garantisce le seguenti due "avviene prima" regole:

L'attore inviare regola: l'invio del messaggio a un attore avviene prima che il messaggio venga ricevuto dallo stesso attore. Regola di elaborazione successiva dell'attore : l'elaborazione di un messaggio avviene prima dell'elaborazione del messaggio successivo da parte dello stesso attore prima del .

Si prega di riferimento the doc per i dettagli.

Mi chiedo come fa Akka a farlo. Ho appena passato il codice sorgente (l'ultimo in questo momento) e ho pensato che ci fosse un blocco prima di eseguire Actor.receive, ma non ho trovato nessun blocco (credo). Infine, ho trovato un commento per ActorCell.invoke:

// coerenza della memoria è gestita dal Mailbox (lettura dello stato della cassetta postale poi l'elaborazione dei messaggi, quindi scrivendo stato di casella di posta

Sì, il Mailbox.status, immagino Ho visto che usano Unsafe per accedere/aggiornare il campo status, ma non riuscivo a capire come questo possa garantire la visibilità della memoria

risposta

13

Ci sono due cose da considerare: il passaggio il m essage e pubblicando correttamente lo stato interno dell'attore.

Il primo è ottenuto dall'implementazione MessageQueue della cassetta postale che utilizzerà le scritture volatili (per il predefinito ConcurrentLinkedQueue) oi blocchi (per un normale LinkedBlockingQueue) per garantire la pubblicazione sicura dell'elemento in coda. L'attore si sincronizzerà con il mittente leggendo gli stessi campi volatili (nel primo caso) o prendendo gli stessi blocchi (nel secondo), quindi tutte le scritture prima che il messaggio venga inviato prima di qualsiasi cosa all'interno dell'attore durante l'elaborazione di quel messaggio .

Lo stato interno dell'attore viene riposto in modo sicuro anche quando è stato riprogrammato su un thread diverso dallo stato della casella di posta che è stato trovato: dopo l'elaborazione di un batch di messaggi (definito dal parametro throughput) la cassetta postale è impostata su "non pianificata "Status, che è una scrittura volatile (in realtà Unsafe.compareAndSetInt(), che ha la stessa semantica). Prima che l'attore inizi ad elaborare i messaggi, legge lo stato della casella utilizzando Unsafe.getIntVolatile, che si sincronizza con la scrittura precedente, quindi tutte le scritture eseguite dall'attore durante l'ultimo batch di messaggi avvengono, prima di tutte le letture durante questo batch.

Si può leggere di più sulla semantica delle operazioni coinvolti here, tenendo presente che i metodi su *Volatilesun.misc.Unsafe obbediscono alle stesse regole per Atomic*Reference.

+0

Gli stati interni di questo attore medio sono protetti da Mailbox.status? –

+0

sì, precisamente. –

+0

Grazie, Roland! Ispezionando AbstractQueuedSynchronizer, lo capisco finalmente. –

Problemi correlati