Qual è la differenza tra: architetture asincrone, non bloccanti, Event-Base?


86
  1. Qual è la differenza tra:

    • Asincrono ,
    • Non bloccante e
    • Architetture basate su eventi ?
  2. Qualcosa può essere sia asincrono che non bloccante (e basato su eventi )?

  3. Cosa è più importante nella programmazione, avere qualcosa: asincrono, non bloccante e / o base di eventi (o tutti e 3)?

Se potessi fornire esempi, sarebbe fantastico.

Questa domanda viene posta perché stavo leggendo questo fantastico articolo di StackOverflow su un argomento simile ma non risponde alle mie domande sopra.

Risposte:


91

Asincrono Asincrono significa letteralmente non sincrono. L'email è asincrona. Mandi una mail, non ti aspetti di ricevere una risposta ORA. Ma non è non bloccante. In sostanza, ciò che significa è un'architettura in cui i "componenti" si inviano messaggi a vicenda senza aspettarsi una risposta immediata. Le richieste HTTP sono sincrone. Invia una richiesta e ottieni una risposta.

Non bloccante Questo termine viene utilizzato principalmente con IO. Ciò significa che quando effettui una chiamata di sistema, tornerà immediatamente con qualsiasi risultato abbia senza mettere il thread a dormire (con alta probabilità). Ad esempio, le chiamate di lettura / scrittura non bloccanti ritornano con tutto ciò che possono fare e si aspettano che il chiamante esegua di nuovo la chiamata. try_lock, ad esempio, è una chiamata non bloccante. Si bloccherà solo se il blocco può essere acquisito. La semantica usuale per le chiamate di sistema è bloccante. read aspetterà fino a quando non avrà alcuni dati e metterà in stop il thread chiamante.

Base eventi Questo termine deriva da libevent. le chiamate di lettura / scrittura non bloccanti di per sé sono inutili perché non ti dicono "quando" dovresti richiamarle (riprova). select / epoll / IOCompletionPort ecc. sono meccanismi diversi per scoprire dal sistema operativo "quando" queste chiamate dovrebbero restituire dati "interessanti". libevent e altre librerie simili forniscono wrapper su queste funzionalità di monitoraggio degli eventi fornite da vari sistemi operativi e forniscono un'API coerente con cui lavorare che gira attraverso i sistemi operativi. L'IO non bloccante va di pari passo con Event-base.

Penso che questi termini si sovrappongano. Ad esempio, il protocollo HTTP è sincrono ma l'implementazione HTTP che utilizza IO non bloccante può essere asincrona. Anche in questo caso una chiamata API non bloccante come read / write / try_lock è sincrona (fornisce immediatamente una risposta) ma la "gestione dei dati" è asincrona.


2
Buon punto sul non blocco che richiede un polling costante, mentre l'asincronia può essere basata su push.
Alexander Torstling

Hai definito sincrono come ricevere una risposta immediata, ma quando eseguo Google Synchronous tutti i dizionari lo definiscono come "che accade nello stesso momento", non "risposta immediata".
IntelliData

4
Come vengo bloccato quando invio un'e-mail ma non aspetto una risposta? Posso andare a farmi gli affari miei in attesa di una risposta.
Koray Tugay

20

In un hardware asincrono, il codice chiede a un'entità di fare qualcosa ed è libero di fare altre cose mentre l'azione viene eseguita; una volta completata l'azione, l'entità in genere segnalerà il codice in qualche modo. Un'architettura non bloccante prenderà nota delle azioni che si verificano spontaneamente a cui il codice potrebbe essere interessato e consentirà al codice di chiedere quali azioni si sono verificate, ma il codice verrà a conoscenza di tali azioni solo quando le chiede esplicitamente. Un'architettura basata sugli eventi notificherà in modo affermativo il codice quando gli eventi si verificano spontaneamente.

Considera una porta seriale, dalla quale il codice vorrà ricevere 1.000 byte.

In un'architettura di blocco-lettura, il codice aspetterà fino all'arrivo di 1.000 byte o deciderà di rinunciare.

In un'architettura di lettura asincrona, il codice dirà al driver che vuole 1.000 byte e verrà avvisato quando sono arrivati ​​1.000 byte.

In un'architettura non bloccante, il codice può chiedere in qualsiasi momento quanti byte sono arrivati ​​e può leggere uno o tutti questi dati quando lo ritiene opportuno, ma l'unico modo in cui può sapere quando sono arrivati ​​tutti i dati è chiedere; se il codice vuole scoprire entro un quarto di secondo quando è arrivato il millesimo byte, deve controllare ogni quarto di secondo circa.

In un'architettura basata sugli eventi, il driver della porta seriale avviserà l'applicazione ogni volta che arrivano dati. Il driver non saprà quanti byte richiede l'applicazione, quindi l'applicazione deve essere in grado di gestire le notifiche per importi inferiori o superiori a quelli richiesti dall'applicazione.


5

Quindi, per rispondere alla tua prima e seconda domanda:

Il non blocco è effettivamente lo stesso dell'asincrono: effettui la chiamata e otterrai un risultato in seguito, ma mentre ciò accade puoi fare qualcos'altro. Il blocco è l'opposto. Aspetti il ​​ritorno della chiamata prima di continuare il tuo viaggio.

Ora il codice asincrono / non bloccante sembra assolutamente fantastico, e lo è. Ma ho parole di avvertimento. Async / Non-blocking sono ottimi quando si lavora in ambienti limitati, come in un telefono cellulare ... considera CPU / memoria limitate. È utile anche per lo sviluppo front-end, in cui il codice deve reagire in qualche modo a un widget dell'interfaccia utente.

L'asincronia è fondamentale per il funzionamento di tutti i sistemi operativi: eseguono operazioni in background e attivano il codice quando hanno fatto ciò che hai chiesto, e quando la chiamata fallisce, ti viene detto che non l'ha fatto funziona tramite un'eccezione o un qualche tipo di codice di ritorno / oggetto di errore.

Nel momento in cui il tuo codice richiede qualcosa che richiederà un po 'di tempo per rispondere, il tuo sistema operativo sa che può darsi da fare con altre cose. Il tuo codice: un processo, thread o equivalente, blocchi. Il tuo codice è totalmente ignaro di cos'altro sta succedendo nel sistema operativo mentre attende che venga stabilita la connessione di rete, o mentre attende quella risposta da una richiesta HTTP, o mentre attende quella lettura / scrittura di un file, e presto. Il codice potrebbe "semplicemente" essere in attesa di un clic del mouse. Quello che stava realmente accadendo in quel periodo era che il tuo sistema operativo gestiva, pianificava e reagiva senza problemi agli "eventi" - cose che il sistema operativo cercava, come la gestione della memoria, I / O (tastiera, mouse, disco, internet), altre attività, ripristino da errori, ecc.

I sistemi operativi sono dannatamente hard-core. Sono davvero bravi a nascondere tutte le complicate cose asincrone / non bloccanti al programmatore. Ed è così che la maggior parte dei programmatori è arrivata a dove siamo oggi con il software. Ora stiamo raggiungendo i limiti della CPU, le persone dicono che le cose possono essere fatte in parallelo per migliorare le prestazioni. Ciò significa che Async / non-blocking sembra una cosa molto favorevole da fare, e sì, se il tuo software lo richiede, posso essere d'accordo.

Se stai scrivendo un server web back-end, procedi con cautela. Ricorda che puoi ridimensionare orizzontalmente per molto meno. Netflix / Amazon / Google / Facebook sono ovvie eccezioni a questa regola, semplicemente perché risulta più economico per loro utilizzare meno hardware.

Ti dirò perché il codice asincrono / non bloccante è un incubo con i sistemi di back-end ...

1) Diventa una negazione del servizio sulla produttività ... devi pensare MOLTO di più e commetti molti errori lungo la strada.

2) Le tracce dello stack nel codice reattivo diventano indecifrabili: è difficile sapere cosa ha chiamato cosa, quando, perché e come. Buona fortuna con il debug.

3) Devi pensare di più a come le cose falliscono, specialmente quando molte cose tornano fuori uso rispetto a come le hai inviate. Nel vecchio mondo facevi una cosa alla volta.

4) È più difficile da testare.

5) È più difficile da mantenere.

6) È doloroso. La programmazione dovrebbe essere una gioia e un divertimento. Solo i masochisti amano il dolore. Le persone che scrivono quadri concorrenti / reattivi sono sadici.

E sì, ho scritto sia sincronizzato che asincrono. Preferisco sincrono poiché 99,99 delle applicazioni back-end possono cavarsela con questo paradigma. Le app front-end richiedono codice reattivo, senza dubbio, e questo è sempre stato il modo.

  1. Sì, il codice può essere asincrono, non bloccante e basato su eventi.

  2. La cosa più importante nella programmazione è assicurarsi che il codice funzioni e risponda in un periodo di tempo accettabile. Attenersi a quel principio chiave e non si può sbagliare.


** AGGIORNAMENTO ** Dopo aver giocato con Go, e aver capito i canali e le routine di go, devo dire che in realtà mi piace rendere il mio codice più concorrente, perché i costrutti del linguaggio prendono tutto il dolore dagli autori di framework sadici. Abbiamo una "parola sicura" nel mondo dell'elaborazione asincrona - e questo è "Go!"
user924272

4

Per me non-blocking significa che l'esecuzione di un'azione in un thread non dipende dall'esecuzione di altri thread, in particolare non richiede una sezione critica.

Asincrono significa che l'esecuzione avviene al di fuori del flusso del chiamante ed è potenzialmente differita. L'esecuzione avviene in genere in un altro thread.

La lettura dei dati simultanei non blocca (non è necessario bloccarli), ma è sincrona. Al contrario, la scrittura simultanea dei dati in modo sincrono è un blocco (richiede un blocco esclusivo). Un modo per renderlo non bloccante dal punto di vista del flusso principale è rendere asincrone le scritture e posticiparne l'esecuzione.

Il concetto di evento è qualcos'altro, che in parole povere significa che sei informato quando accade qualcosa. Se le scritture sono state eseguite in modo asincrono, un evento può essere generato per informare altre parti del sistema una volta che la scrittura è stata eseguita. Le altre parti risponderanno all'evento. Il sistema può essere costruito esclusivamente sugli eventi come unico modo per comunicare tra i componenti (si pensi al modello dell'attore), ma non deve essere necessariamente così.

I tre termini sono correlati, ma per me sono concetti diversi. Può essere che le persone li usino in un modo in qualche modo intercambiabile.


2

In genere, un'architettura non bloccante si basa su chiamate di metodo che, sebbene possano essere eseguite a lungo sul thread di lavoro , non bloccano il thread chiamante . Se il thread chiamante deve acquisire informazioni sull'attività o dall'attività che il thread di lavoro sta eseguendo, spetta al thread chiamante farlo.

Un'architettura basata su eventi si basa sul concetto di codice eseguito in risposta agli eventi che vengono attivati. La tempistica dell'esecuzione del codice generalmente non è deterministica, ma gli eventi possono invocare metodi di blocco; solo perché un sistema è basato sugli eventi non significa che tutto ciò che fa non stia bloccando.

In genere, un'architettura asincrona è un'architettura basata su eventi e non bloccante.

Quando viene effettuata una chiamata asincrona, i gestori di eventi vengono registrati con l'API che fornisce servizi di sincronizzazione, al fine di notificare al chiamante che è accaduto qualcosa a cui il chiamante è interessato. La chiamata quindi ritorna immediatamente (comportamento non bloccante) e il chiamante è libero di continuare l'esecuzione. Quando gli eventi vengono restituiti al processo chiamante, verranno gestiti su alcuni thread in quel processo.

È importante capire se gli eventi verranno gestiti sullo stesso thread o meno, poiché ciò influirà sulla natura non bloccante dell'esecuzione, ma non sono personalmente a conoscenza di alcuna libreria che esegue la gestione dell'esecuzione asincrona su un singolo thread.

Ho rimosso il paragrafo precedente perché non è strettamente corretto come affermato. Il mio intento era quello di dire che anche se le operazioni nel sistema non sono bloccanti, come effettuare chiamate a una struttura del sistema operativo e continuare l'esecuzione, la natura dell'esecuzione a thread singolo significa che quando gli eventi vengono attivati, saranno in competizione con altre attività di elaborazione per il tempo di calcolo sul thread.


Il tuo ultimo paragrafo non contraddice la tua affermazione che "l'architettura asincrona è ... non bloccante"
nickb

Immagino di non aver fatto un ottimo lavoro nell'affrontare la parte "definizioni" della tua domanda; Pubblicherò un aggiornamento. Ma no, la natura dell'esecuzione a thread singolo è che ogni operazione si blocca intrinsecamente mentre è in esecuzione , il che rende l'asincronia ancora più utile.
Matt Mills
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.