Codifica linea retta - In che modo il multithreading semplifica il flusso di lavoro asincrono?

-1

L'autore Java menziona: I thread possono semplificare lo sviluppo di sistemi complessi trasformando il complicato codice asincrono in un codice lineare più semplice.

Anche in questo caso il libro dice: I thread rendono più facile modellare come funzionano e interagiscono gli umani, trasformando i flussi di lavoro asincroni in per lo più sequenziali. Possono anche trasformare un codice altrimenti contorto in un codice di linea che è più facile da scrivere, leggi e mantieni.

Non chiaro con sopra due punti.

La mia comprensione è,

1) Il multithreading può essere utilizzato per:

  • Attività che si escludono a vicenda, vincolate alla CPU. Questa è la programmazione parallela.

  • Attività simultanee, vincolate alla CPU. Coinvolge il meccanismo di sincronizzazione.

2) Il codice asincrono (con ciclo di eventi) è rilevante per le attività reciprocamente esclusive che sono vincolate all'IO. Questo è un codice a thread singolo.

Modifica dopo aver letto i commenti:

La programmazione asincrona è come, campione di scacchi, Polgar (è CPU) che gioca con più giocatori di scacchi amatoriali (sono compiti). La natura di questo gioco è amatoriale (compito) e richiede un po 'di tempo prima che Polgar (CPU) possa tornare con la prossima mossa.

Come è implementato Async?

  • Capacità di attività - Sospendi e amp; Riprendi
  • Ciclo eventi che pianifica queste attività

Non c'è più di un thread coinvolto.

I / O non bloccanti riguardano essenzialmente select() chiamata di sistema UNIX, sotto il cofano. Ad esempio, il codice Python di seguito,

def runForever(self):
        while True:
            readers, _, _ = select.select(self.readers, [], [])
            for reader in readers:
                reader.onRead()

L'IO non bloccante è un modello di programmazione completamente diverso rispetto all'IO asincrono. Ma,

Un modello di programmazione può unificare tutti e tre, non bloccanti, la natura asincrona & supporto multithread? Sì. Il motore Chrome V8 è un esempio, mostrato in questo diagramma .

In che modo i problemi di guida multi-threading risolvono il codice asincrono, per fornire la codifica in linea retta?

    
posta user1787812 07.10.2017 - 12:56
fonte

2 risposte

4

Preferiresti scrivere:

void foo(Channel<Channel<int>> chan1) {
    chan1.read((Channel<int> chan2) -> {
        chan2.read((int result) -> {
            bar(result);
        });
    });
}

o

void foo(Channel<Channel<int>> chan1) {
    Channel<int> chan2 = chan1.read();
    int result = chan2.read();
    bar(result);
}

o anche:

void foo(Channel<Channel<int>> chan1) {
    bar(chan1.read().read());
}

Per non parlare del fatto che il primo esempio sarebbe in pre-lambda Java. Cose come il futuro e le promesse possono rendere un po 'più bello il primo esempio, ma non elimineranno la fondamentale perdita di disciplina dello stack. Questo influenza l'ambito delle variabili e il modo in cui le eccezioni si propagano. try / catch non funziona più in modo significativo. Esempi più complicati di quelli sopra illustrano chiaramente che il futuro e le promesse fanno uno scarso lavoro nel recuperare uno stile di "codice lineare".

La programmazione asincrona è una forma di programmazione concorrente. Hanno fondamentalmente gli stessi casi d'uso e, in particolare, entrambi vanno bene per i carichi di lavoro legati all'IO. Sono persino doppi l'uno rispetto all'altro . E in particolare relativo a che , non c'è bisogno che i thread siano processi a livello di OS, quindi i thread "leggeri" o "verdi" supportati da molte lingue che spesso non forniscono parallelismo (come nell'utilizzo di più core).

    
risposta data 07.10.2017 - 13:26
fonte
2

Leggi prima questo:

Eric Lippert ha già scritto un'ottima risposta su Stack Overflow che dovrebbe anche rispondere alla tua domanda: Qual è la differenza tra la programmazione asincrona e il multithreading?

TL; DR

La tua impressione è giusta; il multi-threading non migliorerebbe gli aspetti prestazionali delle attività legate all'IO.

Ciò che dice l'autore Java (come citato da OP) , mentre non migliorerebbe le prestazioni, riduce la complessità del tuo codice.

Obiettivi diversi, conclusioni diverse.

La mia risposta si concentra sull'uso della terminologia e il problema della confusione.

Ci sono diversi livelli di "can" . Il primo è il meno generalizzabile e il terzo è il più generalizzabile.

  • Che è possibile a tutti
    • (vale a dire senza considerare meriti e sforzi)
  • È vantaggioso farlo in base a criteri specifici
    • (ad esempio in grado di ridurre i tempi di completamento sfruttando i core CPU inutilizzati)
  • Che è generalmente raccomandato per le situazioni date dopo aver preso in considerazione un'ampia gamma di criteri
    • (cioè c'è un elenco di criteri di accompagnamento considerato)
    • (ma, fa anche molte supposizioni su "il caso / i bisogni generali", il che significa che qualcuno con un requisito insolito potrebbe trovarlo non applicabile.)

Quando si menzionano "task mutualmente esclusivi", un modo migliore per dire che si tratta di attività che possono essere eseguite indipendentemente e che non ostacolano e / o interferiscono reciprocamente quando vengono eseguite simultaneamente (come in più core CPU) o contemporaneamente ("sovrapposti" o "in modo asincrono" o "commutazione di attività").

È sempre possibile, e di solito è vantaggioso, avere attività eseguibili in modo indipendente eseguite su più CPU. L'eccezione a questa regola è se le attività sono troppo piccole, quindi i costi generali (soprattutto il tempo di attesa dovuto alla consegna di attività e risultati tra le CPU) potrebbero rovinare i risparmi.

Asincrono è un aggettivo che significa grosso modo punteggiato. Significa che un'attività non viene eseguita continuamente. Passa da esecuzione a pausa (blocco). In generale sta gradualmente progredendo verso l'obiettivo (completamento).

Asincrono può riferirsi a:

  • Lo stile di codifica,
  • Funzioni sintattiche e di generazione del codice fornite da un linguaggio di programmazione,
  • Il modo generale in cui viene eseguito un compito di livello superiore, un fatto che deve essere giudicato in modo soggettivo.

Quando la programmazione asincrona viene eseguita su un linguaggio di programmazione che non fornisce il miglior zucchero sintattico, il risultato è un codice più complicato che è più difficile da capire, mantenere e risolvere. Pertanto, viene fornito con il consiglio (o, una pausa dal consiglio generale) che, se la complessità del codice è troppo alta, allora è consigliabile per uno abbandonare il tentativo di programmazione asincrona e tornare ad un stile di codifica sincrono.

Se la lingua fornisce molto zucchero sintattico per essa, allora è possibile programmare molto in stile di programmazione asincrona senza subire la complessità del codice.

Il codice asincrono non è richiesto per essere a thread singolo. Infatti, in C # è possibile combinare la programmazione asincrona e il multithreading (*), come spiegato nella risposta di Eric Lippert (vedere la parte superiore della risposta per il collegamento).

(*) Crea solo un "come faccio a tornare al chiamante" / "codice in esecuzione sul thread sbagliato" diavolo. Per questo motivo si consiglia di avere un "master thread" incaricato di delegare le attività e questo "master thread" implementerà un ciclo di eventi, che è il meccanismo tramite il quale riceverà invocazione, comunicazione e completamento della procedura da altre attività o thread di lavoro.

A volte è possibile scegliere un'architettura asincrona e single-threaded a causa delle limitazioni tecniche di una o più librerie o framework che utilizza. Ad esempio, quando si programma su Windows, la GUI è in genere a thread singolo, il che significa che non è thread-safe per essere invocato da un thread che non è il thread principale.

La parola "I / O bound" è di solito un termine improprio. Fondamentalmente significa "compiti che richiedono tempo per finire ma non sono vincolati alla CPU".

Ad esempio, un'attività che a volte viene detta "vincolata I / O" implica solo un po 'di trasmissione dei dati. Ad esempio, i dati vengono sottoposti a crunch su un server remoto; l'attività del computer locale è semplicemente in attesa che il server remoto pronunci "done".

risposta data 07.10.2017 - 15:24
fonte