asincrono vs non bloccante

Qual è la differenza tra chiamate asincrone e non bloccanti? Anche tra il blocco e le chiamate sincrone (con esempi per favore)?

In molte circostanze sono nomi diversi per la stessa cosa, ma in alcuni contesti sono piuttosto diversi. Quindi dipende. La terminologia non viene applicata in modo totalmente coerente nell’intero settore del software.

Ad esempio, nell’API classic socket, un socket non bloccante è uno che restituisce immediatamente un messaggio di errore speciale “bloccherebbe”, mentre un socket di blocco avrebbe bloccato. Devi usare una funzione separata come select o poll per scoprire quando è il momento giusto per riprovare.

Ma i socket asincroni (come supportati da Windows Sockets), o il pattern IO asincrono utilizzato in .NET, sono più convenienti. Chiami un metodo per iniziare un’operazione e il framework ti richiama quando ha finito. Anche qui, ci sono differenze fondamentali. I socket asincroni Win32 “eseguono il marshalling” dei loro risultati su uno specifico thread GUI passando i messaggi Window, mentre .NET I / O asincroni è a thread libero (non si sa su quale thread verrà richiamato il callback).

Quindi non sempre significano la stessa cosa. Per distillare l’esempio del socket, potremmo dire:

  • Blocco e sincrono significano la stessa cosa: tu chiami l’API, blocca il thread finché non ha una sorta di risposta e te la restituisce.
  • Non bloccante significa che se una risposta non può essere restituita rapidamente, l’API restituisce immediatamente un errore e non fa nient’altro. Quindi ci deve essere un modo correlato per interrogare se l’API è pronta per essere chiamata (ovvero, per simulare un’attesa in modo efficiente, per evitare il polling manuale in un ciclo stretto).
  • Asincrono significa che l’API ritorna sempre immediatamente, dopo aver avviato uno sforzo di “background” per soddisfare la richiesta, quindi ci deve essere un modo correlato per ottenere il risultato.
  • Asincrono si riferisce a qualcosa fatto in parallelo , diciamo è un altro thread.
  • Il non blocco si riferisce spesso al polling , ovvero verifica se le condizioni date sono valide (la presa è leggibile, il dispositivo ha più dati, ecc.)

Come probabilmente puoi vedere dalla moltitudine di risposte diverse (e spesso reciprocamente esclusive), dipende da chi chiedi. In alcune arene, i termini sono sinonimi. Oppure potrebbero ciascuno fare riferimento a due concetti simili:

  • Un’interpretazione è che la chiamata farà qualcosa sullo sfondo essenzialmente senza supervisione, al fine di consentire al programma di non essere ostacolato da un lungo processo che non ha bisogno di controllare. L’audio potrebbe essere un esempio: un programma potrebbe chiamare una funzione per riprodurre (ad esempio) un mp3 e da quel momento in poi potrebbe continuare su altre cose lasciandolo al sistema operativo per gestire il processo di rendering dell’audio sull’hardware audio .
  • L’interpretazione alternativa è che la chiamata farà qualcosa che il programma dovrà monitorare, ma permetterà che la maggior parte del processo si verifichi in background, notificando il programma solo nei punti critici del processo. Ad esempio, il file asincrono I / O potrebbe essere un esempio: il programma fornisce un buffer al sistema operativo per scrivere sul file e il sistema operativo notifica il programma solo quando l’operazione è completa o si verifica un errore.

In entrambi i casi, l’intenzione è quella di consentire al programma di non essere bloccato in attesa del completamento di un processo lento – l’unica vera differenza è la risposta al programma. Il termine indica il quale cambia anche da programmatore a programmatore, da lingua a lingua o da piattaforma a piattaforma. Oppure i termini possono riferirsi a concetti completamente diversi (come l’uso di sincrono / asincrono in relazione alla programmazione dei thread).

Ci dispiace, ma non credo che esista un’unica risposta giusta che sia globalmente vera.

Mettendo questa domanda nel contesto di NIO e NIO.2 in java 7, l’IO asincrono è un passo più avanzato rispetto al non-blocco. Con le chiamate java NIO non bloccanti, si impostano tutti i canali (SocketChannel, ServerSocketChannel, FileChannel, ecc.) Come tali chiamando AbstractSelectableChannel.configureBlocking(false) . Dopo la restituzione delle chiamate IO, tuttavia, sarà comunque necessario controllare i controlli, ad esempio se e quando leggere / scrivere di nuovo, ecc.
Per esempio,

 while (!isDataEnough()) { socketchannel.read(inputBuffer); // do something else and then read again } 

Con l’api asincrona in java 7, questi controlli possono essere fatti in modi più versatili. Uno dei 2 modi è usare CompletionHandler . Si noti che entrambe le chiamate di read sono non bloccanti.

 asyncsocket.read(inputBuffer, 60, TimeUnit.SECONDS /* 60 secs for timeout */, new CompletionHandler() { public void completed(Integer result, Object attachment) {...} public void failed(Throwable e, Object attachment) {...} } } 

sincrono / asincrono descrive la relazione tra due moduli.
bloccare / non bloccare è descrivere la situazione di un modulo.

Un esempio:
Modulo X: “I”.
Modulo Y: “libreria”.
X chiede a Y: hai un libro chiamato “primer c ++”?

1) blocco: prima che Y risponda a X, X continua ad aspettare lì per la risposta. Ora X (un modulo) sta bloccando. X e Y sono due thread o due processi o un thread o un processo? noi NON sappiamo.

2) non bloccante: prima che Y risponda a X, X se ne va e fa altre cose. X può tornare ogni due minuti per verificare se Y ha terminato il suo lavoro, o X non tornerà finché non lo chiama. Non lo sappiamo Sappiamo solo che X può fare altre cose prima che Y finisca il suo lavoro. Qui X (un modulo) non è bloccante. X e Y sono due thread o due processi o un processo? noi NON sappiamo. MA siamo sicuri che X e Y non potrebbero essere un thread.

3) sincrono: prima che Y risponda a X, X rimane lì ad aspettare la risposta. Significa che X non può continuare fino a quando Y termina il suo lavoro. Ora diciamo: X e Y (due moduli) sono sincroni. X e Y sono due thread o due processi o un thread o un processo? noi NON sappiamo.

4) asincrono: prima che Y risponda a X, X lascia lì e X può fare altri lavori. X non tornerà prima che Y lo chiami. Ora diciamo: X e Y (due moduli) sono asincroni. X e Y sono due thread o due processi o un processo? noi NON sappiamo. MA siamo sicuri che X e Y non potrebbero essere un thread.

Si prega di prestare attenzione alle due frasi in grassetto sopra. Perché la frase in grassetto nel 2) contiene due casi mentre la frase in grassetto nel 4) contiene solo un caso? Questa è una chiave della differenza tra non bloccante e asincrono.

Ecco un tipico esempio di non blocco e sincrono:

 // thread X while (true) { msg = recv(Y, NON_BLOCKING_FLAG); if (msg is not empty) { break; } sleep(2000); // 2 sec } // thread Y // prepare the book for X send(X, book); 

Puoi vedere che questo design è non-bloccante (puoi dire che la maggior parte del tempo questo loop fa qualcosa di assurdo, ma negli occhi della CPU, X è in esecuzione, il che significa che X non è bloccante) mentre X e Y sono sincroni perché X può continuare a fare qualsiasi cosa (X non può saltare fuori dal loop) finché non riceve messaggi da Y.
Normalmente in questo caso, rendere X blocco è molto meglio perché il non-blocco spende molte risorse per un ciclo stupido. Ma questo esempio è utile per aiutarti a capire il fatto: il non blocco non significa asincrono.

Le quattro parole ci rendono facilmente confusi, quello che dovremmo ricordare è che le quattro parole servono per la progettazione dell’architettura. Imparare a progettare una buona architettura è l’unico modo per distinguerli.

Ad esempio, possiamo progettare un tale tipo di architettura:

 // Module X = Module X1 + Module X2 // Module X1 while (true) { msg = recv(many_other_modules, NON_BLOCKING_FLAG); if (msg is not null) { if (msg == "done") { break; } // create a thread to process msg } sleep(2000); // 2 sec } // Module X2 broadcast("done"); // Module Y // prepare the book for X send(X, book); 

Nell’esempio qui, possiamo dirlo

  • X1 non è bloccante
  • X1 e X2 sono sincroni
  • X e Y sono asincroni

Se necessario, puoi anche descrivere i thread creati in X1 con le quattro parole.

Le cose più importanti sono: quando usiamo sincrono anziché asincrono? quando usiamo il blocco anziché il non-blocco?

Perché Nginx non blocca? Perché il blocco di Apache?

Per fare una buona scelta, devi analizzare le tue necessità e testare le prestazioni di diverse architetture. Non esiste un’architettura che sia adatta a vari bisogni.

Una chiamata non bloccante ritorna immediatamente con qualsiasi dato disponibile: il numero intero di byte richiesti, meno o nessuno.

Una chiamata asincrona richiede un trasferimento che verrà eseguito nella sua interezza (interezza), ma verrà completato in un momento futuro.

Non bloccante: questa funzione non attenderà mentre è in pila.

Asincrono: il lavoro può continuare per conto della chiamata di funzione dopo che quella chiamata ha lasciato lo stack

Chiamata di blocco : il controllo ritorna solo al termine della chiamata.

Chiamata non bloccante : il controllo ritorna immediatamente. Il SO successivo in qualche modo notifica al processo che la chiamata è completa.


Programma sincrono : un programma che utilizza le chiamate di blocco . Per non bloccarsi durante la chiamata, deve avere 2 o più thread (è per questo che si chiama Synchronous – i thread sono in esecuzione in modo sincrono).

Programma asincrono : un programma che utilizza le chiamate Non bloccanti . Può contenere solo 1 thread e rimanere interattivo.

Synchronous è definito come accade nello stesso momento.

Asincrono è definito come non accade nello stesso momento.

Questo è ciò che provoca la prima confusione. Synchronous è in realtà ciò che è noto come parallelo. Mentre asincrono è sequenziale, fallo, quindi fallo.

Ora l’intero problema riguarda la modellazione di un comportamento asincrono, perché hai alcune operazioni che richiedono la risposta di un’altra prima che possa iniziare. Quindi è un problema di coordinamento, come saprai che ora puoi iniziare quell’operazione?

La soluzione più semplice è conosciuta come blocco.

Il blocco è quando si sceglie semplicemente di aspettare che venga eseguita l’altra cosa e di restituire una risposta prima di passare all’operazione che ne ha avuto bisogno.

Quindi, se hai bisogno di mettere il burro sul pane tostato, e quindi prima devi brindare all’educato. Il modo in cui li avresti coordinati è che prima avresti brindato, poi fissi il tostapane senza interruzioni fino a quando non si apre il brindisi, e poi avresti messo del burro su di loro.

È la soluzione più semplice e funziona molto bene. Non c’è un vero motivo per non usarlo, a meno che tu non abbia altre cose da fare che non richiedono il coordinamento con le operazioni. Ad esempio, facendo alcuni piatti. Perché aspettare di non guardare fisso il tostapane per far scoppiare il brindisi, quando sai che ci vorrà un po ‘di tempo e potresti lavare un intero piatto mentre finisce?

È qui che entrano in gioco altre due soluzioni conosciute come non bloccanti e asincrone.

Il non blocco è quando si sceglie di fare altre cose non correlate mentre si attende che l’operazione venga eseguita. Verifica della disponibilità della risposta come meglio credi.

Quindi, invece di guardare il tostapane per farlo scoppiare. Vai e lava un intero piatto. E poi sbirci al tostapane per vedere se i toast sono spuntati. Se non lo sono, vai a lavare un altro piatto, controllando il tostapane tra ogni piatto. Quando vedi che i toast sono saltati, smetti di lavare i piatti, e invece prendi il toast e vai a mettere il burro su di essi.

Dover controllare costantemente i toast può essere fastidioso, immagina che il tostapane sia in un’altra stanza. Tra una pietanza e l’altra, sprechi il tuo tempo andando in quell’altra stanza per controllare il brindisi.

Qui arriva asincrono.

Asincrono è quando si sceglie di fare altre cose non correlate mentre si attende che l’operazione venga eseguita. Invece di controllarlo, delegate il lavoro di controllo a qualcos’altro, potrebbe essere l’operazione stessa o un osservatore, e avete quella cosa notificare e possibilmente interromperla quando la risposta è disponibile in modo da poter procedere all’altra operazione che ne aveva bisogno.

È una strana terminologia. Non ha molto senso, dal momento che tutte queste soluzioni sono modi per creare un coordinamento asincrono delle attività dipendenti. Ecco perché preferisco chiamarlo evento.

Quindi per questo, decidi di aggiornare il tuo tostapane in modo che emetta un segnale acustico quando i toast sono fatti. Ti capita di essere costantemente in ascolto, anche mentre stai facendo i piatti. Sentendo il segnale acustico, ti metti in coda nella memoria che non appena hai finito di lavare il tuo piatto attuale, ti fermi e vai a mettere il burro sul pane tostato. Oppure puoi scegliere di interrompere il lavaggio del piatto attuale e affrontare subito il brindisi.

Se hai problemi nell’udire il segnale acustico, puoi far controllare il tostapane dal tuo partner e venire a dirti quando il toast è pronto. Il tuo partner può scegliere tra le tre strategie sopra elencate per coordinare il suo compito di guardare il tostapane e dirti quando sono pronti.

In una nota finale, è bene capire che mentre non si bloccano e asincrono (o ciò che preferisco chiamare evented) ti permettono di fare altre cose mentre aspetti, anche tu non ne hai. È ansible scegliere di eseguire il ciclo continuo controllando lo stato di una chiamata non bloccante, senza fare altro. Spesso è peggio che bloccarlo (come guardare il tostapane, poi allontanarlo, quindi tornare indietro fino a quando non viene eseguito), quindi un sacco di API non bloccanti ti permettono di passare da una modalità di blocco. Per evento, puoi solo aspettare inattivo fino a quando non ti viene notificato. In questo caso, l’aspetto negativo è che l’aggiunta della notifica era complessa e potenzialmente dispendiosa all’inizio. Dovevi comprare un nuovo tostapane con funzionalità beep o convincere il tuo partner a guardarlo per te.

E ancora una cosa, è necessario rendersi conto dei compromessi che forniscono tutti e tre. Uno non è ovviamente migliore degli altri. Pensa al mio esempio Se il tuo tostapane è così veloce, non avrai il tempo di lavare un piatto, nemmeno di iniziare a lavarlo, è quanto è veloce il tuo tostapane. Iniziare su qualcos’altro in quel caso è solo uno spreco di tempo e fatica. Il blocco funzionerà. Allo stesso modo, se il lavaggio di un piatto richiederà 10 volte di più della tostatura. Devi chiederti cosa è più importante fare? Il brindisi potrebbe diventare freddo e difficile a quel punto, non ne vale la pena, anche il blocco lo farà. O dovresti scegliere cose più veloci da fare mentre aspetti. C’è di più ovviamente, ma la mia risposta è già piuttosto lunga, il mio punto è che devi riflettere su tutto questo e sulla complessità di implementare ciascuno per decidere se ne vale la pena, e se effettivamente migliorerà il tuo rendimento o la tua performance.

Modificare:

Anche se questo è già lungo, voglio anche che sia completo, quindi aggiungerò altri due punti.

1) Esiste anche comunemente un quarto modello noto come multiplexato . Questo è quando mentre aspetti un compito, ne inizi un altro e mentre aspetti entrambi, ne inizi uno di più, e così via, finché non hai avviato molte attività e poi, attendi inattivo, ma su tutte loro. Quindi, appena fatto, puoi procedere con la gestione della sua risposta, e poi tornare ad aspettare gli altri. È noto come multiplex, perché mentre aspetti, devi controllare ogni attività una dopo l’altra per vedere se sono fatte, ad vitam, finché non lo si è. È un po ‘un’estensione in cima al normale non-blocco.

Nel nostro esempio sarebbe come avviare il tostapane, poi la lavastoviglie, poi il microonde, ecc. E poi aspettare qualcuno di loro. Dove controlleresti il ​​tostapane per vedere se è fatto, in caso contrario controlleresti la lavastoviglie, se no, il microonde, e di nuovo in giro.

2) Anche se credo che sia un grosso errore, sincrono è spesso usato per significare una cosa alla volta. E asincrono molte cose alla volta. In questo modo vedrai il blocco sincrono e il non blocco utilizzati per fare riferimento al blocco e al non blocco. E blocco asincrono e non blocco usato per riferirsi a multiplexed e evented.

Non capisco davvero come siamo arrivati. Ma quando si tratta di IO e calcolo, sincrono e asincrono si riferiscono spesso a ciò che è meglio conosciuto come non sovrapposto e sovrapposto. Cioè, asincrono significa che IO e il calcolo sono sovrapposti, aka, accadendo contemporaneamente. Mentre sincrono significa che non lo sono, quindi accade in modo sequenziale. Per i sincroni non bloccanti, ciò significherebbe che non si avvia altro IO o Calcolo, è solo occupato ad attendere e simulare una chiamata di blocco. Vorrei che le persone smettessero di abusare di sincrono e asincrono in quel modo. Quindi non lo sto incoraggiando.

Differiscono solo nell’ortografia. Non c’è differenza in ciò a cui si riferiscono. Per essere tecnici si potrebbe dire che differiscono in enfasi. Il non blocco si riferisce al stream di controllo (non blocca). Asynchronous fa riferimento a quando l’evento \ data viene gestito (non in modo sincrono).

I modelli di blocco richiedono l’avvio dell’applicazione per bloccare quando l’I / O è stato avviato. Ciò significa che non è ansible sovrapporre contemporaneamente elaborazione e I / O. Il modello sincrono non bloccante consente la sovrapposizione di elaborazione e I / O, ma richiede che l’applicazione controlli lo stato dell’I / O su base ricorrente. Questo lascia l’I / O asincrono non bloccante, che consente la sovrapposizione di elaborazione e I / O, inclusa la notifica del completamento dell’I / O.

Blocco: il controllo ritorna al richiamo della precessione dopo l’elaborazione di primitivi (sincronizzazione o asincrona) completati

Non blocco: il controllo ritorna in elaborazione immediatamente dopo l’invocazione