Anteprima
Vedrai una selezione di 10 pagine su 41
Programmazione concorrente e distribuita Pag. 1 Programmazione concorrente e distribuita Pag. 2
Anteprima di 10 pagg. su 41.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 6
Anteprima di 10 pagg. su 41.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 11
Anteprima di 10 pagg. su 41.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 16
Anteprima di 10 pagg. su 41.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 21
Anteprima di 10 pagg. su 41.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 26
Anteprima di 10 pagg. su 41.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 31
Anteprima di 10 pagg. su 41.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 36
Anteprima di 10 pagg. su 41.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 41
1 su 41
D/illustrazione/soddisfatti o rimborsati
Disdici quando
vuoi
Acquista con carta
o PayPal
Scarica i documenti
tutte le volte che vuoi
Estratto del documento

Backpressure

Backpressure è la possibilità di un consumatore di dire "sono troppo lento, produttore va piano!" Per pochi dati quindi di solito si usa Observable, ma concettualmente sono la stessa cosa. Importante capire la differenza tra cold e hot observable, i più semplici sono catene cold fredde dove la computazione avviene solo quando un sottoscrittore si sottoscrive, è come se assemblassimo una catena di dati che viene per esempio un database non parte nulla finché non sottoscrivo un sottoscrittore. Quando è hot la sorgente emette a prescindere dei valori e quando il sottoscrittore si aggancia allora si aggancia, parte a osservare da quel momento.

Vengono divisi due momenti fondamentali, assembly time e subscription time. Nell'assembly time non succede nulla, è un momento dichiarativo, sto assemblando la catena computazionale che esprime quello che succederà quando c'è un sottoscrittore che sottoscrive.

nello stesso tempo a runtime ci deve essere la sorgente che ha un meccanismo di emissione dei dati, e così avverrà la computazione

Just è il modo più semplice per creare una sorgente osservabile a partire dalla lista di elementi che gli passo e poi c'è la sottoscrizione

Per quanto riguarda il flusso di controllo, quando non è specificato nulla a eseguire le cose è sempre il thread chiamante, nella forma più semplice quindi la sottoscrizione è bloccante (in questo modo di asincrono non c'è nulla)

FromArray genera un flusso asincrono a partire da un array di elementi

Esiste il concetto di completamento perché secondo Rx Java tutti gli stream dovranno poi completarsi, quindi è possibile dire cosa fare quando è finito il flusso, poi si può reagire anche agli errori, alle eccezioni

Chi non ha capito benissimo la programmazione reattiva la utilizza come il pattern observer, ovvero alla sorgente ci attacco subito il sottoscrittore

l’osservatore che a sua volta fa tutte le operazioni. Qui la differenza è che ciò che si farebbe fare ai listener lo si fa fare agli operatori messi in mezzo, in modo che il listener, il subscriber si ritrovi solo il risultato confezionato. Si crea un flusso quindi, range (1, 20) ad esempio crea un flusso con tutti i valori da 1 a 20, map invece crea un nuovo flusso con i valori che sono il risultato di un mapping della lambda che passo (nell’esempio viene creato un flusso che ha gli elementi al quadrato), un altro operatore ad esempio è la filter che permette di selezionare, di filtrare, creando un nuovo flusso con solo gli elementi che soddisfano il predicato che gli passo (nell’esempio quelli che sono divisibili per 3). Questa sopra è la fase di assembly, ma il tutto parte quando faccio subscribe. DoOnNext() crea un flusso in cui ci sono gli stessi elementi però si ha la possibilità su ogni elemento di chiamare una lambda che fa qualcosa (si usa per ildebug disolito) Esistono anche operatori di composizione che lavorano su più stream. FlatMap è forse l'operatore più usato, dove dati più stream riesce a mapparli in un unico stream appiattendo tutto quindi ad un singolo flusso. Fino adesso abbiamo visto come creare un observable a partire da una lista, da un valore, ecc. Ma se voglio crearmi il mio flusso come mi pare? L'API più semplice è create() che vuole come parametro un lambda, dove poi gli posso specificare onComplete(), onError(), ecc. Fondamentale è usare onNext() per farlo andare avanti col flusso, e anche qui è una soluzione cold perché siamo nella fase di assemblaggio e soltanto quando si chiamerà la subscribe partirà il tutto. Per fare in modo che sia asincrono si crea sempre un observable cold, ma internamente si crea una lambda che genera un flusso di controllo asincrono con un thread separato per generare i vari elementi. Bisogna stare attenti a non chiudere.il main thread sennò si chiude la computazione in generale. Importante ricordarsi che quando si ha il caso cold la computazione parte quando si ha un sottoscrittore, senza sottoscrittore non parte nulla. Nel caso hot la sorgente viene creata come prima, ma per renderla indipendente, ovvero che la generazione parta a prescindere dagli osservatori si deve fare publish() che crea un ConnectableFlowable su cui poi si chiamerà connect() che farà partire la generazione degli elementi a prescindere dagli osservatori. Gli scheduler permettono di specificare su quali thread vengono eseguite le computazioni reattive. Se non specifico nulla, la computazione che viene nascosta, che viene fatta da una catena reattiva, viene fatta dal thread chiamante che prende in carico tutto, generazione, reazione, ecc (che può essere il main thread). Se voglio allocare le computazioni su un pool di thread diverso, devo usare subscribeOn che come.

gliexecutor incapsula la strategia di usare uno o più thread (Schedulers.computation()usa un xed thread pool), ci sono quindi degli scheduler prede niti oppure possocreare il mio

observeOn vuol dire tutti gli operatori che seguono vengono allocati su un usso diesecuzione diversi che dipendono dagli scheduler che speci co, e di erenza delsubscribeOn ha e etto dal punto della catena dove lo utilizzo

Qui inizia a parlare di nuovo di javarx ma lo seguo poco perchè ho già ancheconsegnato l'assignment sulla programmazione reattiva

Di nuovo inizia a parlare della di erenza tra hot e cold, un esempio dove con ilcaso cold se viene aggiunto un sottoscrittore dopo che è stato popolato lo streamnon succede nulla

Poi fa vedere altri operatori da usare sugli stream

Ha spiegato come fare reti di petri per programmazione ad eventi

Ha fatto vedere come ha implementato TLA+ per il primo assignment

Il modulo 3 del corso è importante perché introduce dei modelli

di coordinazione tra processi non basati più sulla memoria condivisa ma sullo scambio di messaggi sincrono, questi modelli possono essere usati anche nel contesto della programmazione distribuita (sono il modello di riferimento in questo secondo caso).

Vedremo nella pratica il modello degli attori con akka come framework, come tecnologia di riferimento.

Il punto centrale di partenza è che esistono due macro-modelli per cui pensare alla programmazione di sistemi a processi, uno a memoria condivisa (es. thread, ecc.) e uno a memoria non condivisa dove si parla ancora di processi ma lavorano tramite uno scambio di messaggi.

Nel modello a scambio di messaggi non c'è mai trasferimento di controllo, non ho più monitor, le uniche primitive che ho per interagire con qualcosa di esterno sono send e receive per inviare e ricevere i messaggi. È un modello che si mappa bene con la rete.

Nella forma più astratta identifico anche:

un canale, visto come mezzo di comunicazione, e nella sintassi lo si può usare proprio come una variabile. Quando eseguo una receive è sempre bloccante di solito, mi blocco in attesa che ci sia almeno un messaggio. I processi condividono qualcosa, e sono i canali, che però non sono variabili condivise, e la send e la receive sono primitive atomiche. Importante, che chiede sempre all'orale, è la differenza tra comunicazione sincrona e asincrona. Sincrona significa che la send è bloccante, quando eseguo la send su un canale mi blocco in attesa che il canale sia ricevuto attraverso una receive dall'altra parte del canale, in questo modo la send e la receive diventano un punto di sincronizzazione, perché io so che quando eseguo una send a fronte del fatto che mi sblocco sono sicuro che mi sono sincronizzato con l'altro processo che ha fatto una receive. La semantica asincrona invece, è il caso in cui la send non è bloccante, la send

haquindi successo anche se dall’altra parte il processo non ha ancora fatto lareceive, ci deve essere una struttura che permetta che i messaggi diventinopersistenti (nel caso più semplice un buffer) usando politiche ad esempio FIFO

Posso usare un canale per fare comunicare due processi ma usare anche lo stesso canale per fare comunicare un processo con più processi, quindi più processi che competono per fare la receive sullo stesso canale, posso avere anche più canali per uno stesso processo

Nascono quindi tipi di schemi differenti, ad esempio one-to-one che è tipica nelle applicazioni sincrone (ad esempio hardware di supercomputer) dove per ogni coppia di processi ci sarà uno specifico canale, quindi non ci sono processi condivisi e se si hanno più processi si avranno più canali in modo da fare comunicare due processi per ogni canale

Lo schema many-to-many è più flessibile e lo stesso canale può essere usato

dapiù sender e più receiverIn ne, quando vedremo gli attori è come se ogni attore avesse il proprio canale(che non è condiviso con nessun altro processo) e si manda il messaggiodirettamente a luiCon questo nuovo approccio alla programmazione scompaiono i componentipassivi (non ci sono più ad esempio passaggi di monitor), ho solo componentiattivi che si scambiano messaggi tra di loro, elimino anche il problema di corsecritiche perchè non condividono memoriaGli attori saranno componenti attivi ma anche reattiviCon questo approccio non esiste valore di ritorno, tutto è modellato con unoscambio di messaggiAkka è il framework più usato a livello industrialeIl modello a scambio di messaggi non è un meccanismo nuovo introdotto, ma èproprio un modo diverso di pensare per la costruzione del software, non usa lamemoria condivisa ma usa la comunicazione (scambio di messaggi) che divental’unico mezzo per

Se ho un processo che deve essere in ascolto su più canali come faccio? C'è la receive, però questa è bloccante, e se ho un solo canale va bene ma se ne ho più non va più.

Viene utilizzato un meccanismo chiamato "selective receive" che esprime la possibilità di mettersi in ascolto su più canali, nasce dal concetto di "guards communication" inventato da Djikstra.

Una guards communication, ovvero una comunicazione con guardia, è una tripla formata da "B (condizione booleana) ; C (stato di comunicazione, di solito receive) -> S (Blocco di stato)".

La regola dice che se una guardia è soddisfacibile (ha successo) allora può essere eseguito lo statement corrispondente.

Da quello che ho capito funziona così, si guarda la condizione booleana delle guardie (una per ogni canale), s...

Dettagli
Publisher
A.A. 2021-2022
41 pagine
SSD Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher luca2695 di informazioni apprese con la frequenza delle lezioni di Programmazione concorrente e distribuita e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Università degli Studi di Bologna o del prof Ricci Alessandro.