Estratto del documento

Introduzione

mercoledì 21 febbraio 2018 14:11

Motivazione principali per scivere programmi concorrenti

Tante cose da fare e processore abbastanza potente

- ▪ Concorrenza virtuale

▪ Processi cooperanti

Per modellare parallelismo del mondo reale

- Quando si hanno più processori (sfrutta parallelismo reale)

-

Sequenziale vs Concorrente

Batch processing: dati di input disponibili preventivamente

- Programmi inter(merda)attivi: periodi in cui programma aspetta che utente fornisca un dato per

- elaborazione

Parallelismo nel mondo reale (fare tante cose contemporaneamente)

Legge di Moore: capacità dei calcolatori aumenta ogni 18 mesi

Processi concorrenti devono programmare e coordinare le loro azioni

Possono portare a nuova condizioni di errore

-

Problemi

Deadlock (ciascuna attività concorrente è in attesa del risultato di un'altra attività per eseguire)

- Race condition (due o più attività simultanee tentano di aggiornare lo stesso oggetto)

- Starvation (a una o più attività simultanee vengono continuamente negate risorse)

-

Proprietà desiderate

Safety (attività concorrenti non interferiscono tra di loro col rischio di corrompere i dati)

- Liveness (attività concorrenti devono fare progressi con le loro attività senza deadlock o starvation)

-

Programmazione in Ambiente Distribuito

Componenti che girano contemporaneamente su più computer

- Utilizzati socket

- Remote Method Invocation (RMI)

- ○ Implementa RPC

○ Client può invocare un metodo su un oggetto remoto in modo trasparente

Organizzazione Client Server

Server (entità che mette a disposizione delle risorse o servizi)

- Client (entità che richiede risorse e servizi al server)

- Richieste e risposte seguono un protocollo (insieme di regole)

-

Programmazione a Eventi

Per la gestione di interfacce a oggetti

Programmazione Concorrente e Distribuita Page 1

Gli Stream di I/O

mercoledì 21 febbraio 2018 16:03

Gestioni di ingresso e uscita, definisce le operazioni il pacchetto java.io

Stream (Flussi): sequenze ordinate di dati, hanno una sorgente o una destinazione

Flussi di Input/Output

Per ricevere dei dati, una app apre lo stream colleggato a una sorgente da cui legge le info

Sorgente può essere in memoria, disco o remota

-

Pacchetto composto da due sezioni:

Flussi di Byte

- ○ Unità di informazione è il byte

○ I/O binario (dati tutti in formato binario)

○ Classi indicate come:

▪ Stream di ingresso

▪ Stream di uscita

Flussi di Caratteri

- ○ Unità di informazione sono caratteri Unicode

○ I/O testuale

○ Classi indicate come:

▪ Lettori

▪ Scrittori

Errori

Se operazioni di ingresso o uscita non vanno a buon fine

Segnalati in due modi:

Cambiando lo stato dello stream

- Lanciando un'eccezione di tipo IOException

-

Ingresso di File Binari

Si utilizza FileInputStream [ FileInputStream in = new FileInputStream(nomeFile); ]

Per leggere un byte si usa il metodo read() che restituisce int con byte letto

Quando non c'è più nulla da leggere read restituisce -1

Scrittura su File Binari

Si utilizza FileOutputStream [ FileOutputStream out = new FileOutputStream(nomeFIle) ]

Per scrivere un byte si usa il metodo write(int c)

Lettura di un File di testo

Si utilizza FileReader Programmazione Concorrente e Distribuita Page 2

Thread e Multi-Thread

lunedì 26 febbraio 2018 11:10

Programma è insieme di istruzioni di alto livello o in linguaggio macchina

Processo è programma in esecuzione (possibile + processi in parallelo grazie a scheduler)

Differenze tra Processi e Thread

Se i processi condividono lo stesso spazio degli indirizzi --> processi leggeri o thread

Se i processi hanno il proprio spazio degli inidrizzi ---------> processi pesanti o processi

Programmazione concorrente: pratica di implementare programmi che contengono più flussi di

esecuzione (thread), creando thread per ogni richiesta

Programmi Concorrenti e Sequenziali

Sequenziale è deterministico

Modello di Memoria Semplificato (SMM)

Utilizza diversi tipi di memoria:

Heap

- Method area

- Program context

-

Sleeping and Blocking

Spesso un thread può essere sospeso per un certo tempo, assume lo stato di sleeping o blocked.

Resta in questo stato per il tempo precisato poi torna ready

Per far partire i thread si utilizza start

Per far si che dopo una start inizi ad eseguire il task t, mandiamo in sleep il metodo main (esempio

slide pag 60)

Sleep()

Mette in attesa un processo senza consumare cicli del processore

È possibile interrompere uno sleep via interrupt, quindi sleep va inserito in un try catch

isAlive()

Testare se il metodo è vivo, il thread viene considerato alive finchè il metodo run() non ritorna

Join()

Attende la terminazione del thread sul quale è richiamato

Per fermare un thread si usa un' interrupt

Usando il flag dell'interrupt e sollevando l'eccezione InterruptException; dovrebbe quindi terminare

l'esecuzione

Yield()

Pemette ad un altro thread di lasciare volontariamente il processore ad un altro thread

Si usa quando non vi è preemption

Programmazione Concorrente e Distribuita Page 3

01 - Thread e MultiThread

lunedì 23 aprile 2018 14:11

Thread e Multi-Thread

Processi leggeri o Thread --> processi condividono lo stesso spazio degli indirizzi

Processi pesanti o processi --> processi hanno il proprio spazio negli indirizzi

Ogni programma in esecuzione è un thread, il main è associato al thread main.

Programmazione concorrente = pratica di implementare programmi che contengano più flussi di

esecuzione (Thread)

Creare un thread

1. Estendere la classe java.lang.Thread

2. Riscrivere (Override) il metodo run()

3. Creare istanza della sottoclassi

4. Richiamare il metodo start() su questa istanza

Limitazione: le classi che estendono Thread non possono estendere altre classi

Il metodo run()

Costituisce l'entry point del thread

- ○ Thread ALIVE --> finchè run() non ritorna

○ Thread DEAD --> quando run() ritorna

Dopo che un thread è DEAD non può essere rieseguito, se no si deve creare una nuova istanza

- Non si può far partire lo stesso thread più volte

-

Approccio alternativo alla creazione di un thread

Si possono creare thread usanda java.lang.Runnable

1. Definire implementazione Runnable

2. Realizzare il metodo run()

3. Creare istanza

4. Instanziare un nuovo Thread passando al costruttore l'istanza che implementa Runnable

5. Richiamare start() su Thread

Programmi concorrenti e sequenziali

Programmi concorrenti hanno proprietà molto diverse dai programmi sequenziali: quest' ultimo

riproduce lo stesso input ogni volta, invece nei programmi concorrenti il comportamento di un

thread dipende da un altro thread

Il metodo run() può essere chiamato più volte

Il metodo start() può essere chiamato solo una volta

Flusso di Controllo

Se ci sono due flussi di esecuzione e l'oggetto A non aspetta che termini l'esecuzione dell' oggetto B,

il programma termina quando tutti i thread non daemon terminano. Un thread daemon fornisce un

servizio generale in background mentre il programma esegue altro.

Thread Daemon

Particolare tipo di thread con:

Priorità molto bassa (eseguiti quando nessun altro thread è in esecuzione)

- Utilizzati come fornitori di servizi per i thread normali

-

JVM termina il programma terminando i thread daemon quando sono gli unici in esecuzione

Stati di un Thread

Born, Ready, Running, Dead

Invochiamo il metodo start -> thread diventa ready

- Quando viene selezionato dallo scheduler diventa Running ed esegue run()

- Programmazione Concorrente e Distribuita Page 4

Quando viene selezionato dallo scheduler diventa Running ed esegue run()

-

Java Thread Scheduling

Come funziona lo scheduler?

JVM schedula l'esecuzione dei thread utilizzando un algoritmo di scheduling preempitive e

- priority based

Tutti i thread hanno una priorità e il thread con la priorità più alta tra quelli ready viene

- schedulato per essere eseguito

Con il diritto di preemption lo scheduler sottrae la CPU al processo e assegna al nuovo

- processo

Politica di Scheduler

Java non specifica il tipo di politica, dipende dal Sistema Operativo

Se i due thread hanno la stessa priorità:

In presenza di scheduling non preemptive eseguirà solo il thread lanciato per primo

- Se vanno entrambi, lo scheduling è preemptive

- ○ Quando scade il quanto di tempo al thread, viene sottratta CPU e passata al thread

Modello di Memoria Semplificato (SMM)

Utilizzato dalla Macchina Virtuale Semplificata (SVM) utilizza diversi tipi di memoria:

Heap (memorizzare oggetti e loro dati)

- Method Area (definizioni della classi e istruzioni compilate)

- Program Context (informazioni uniche per thread come stack e PC)

-

SMM durante l'esecuzione di un Programma Single Thread

SVM crea heap e il thread context, method area e carica i metodi

- Crea il PC con valore non definito

- SVM inserisce un activation record per il main nello stack

- SVM assegna la linea di codice dove si istanzia la classe (PCexe n = new PCexe) al PC e al thread

- PC

SVM esegue la riga 10 - crea istanza della classe Pcexe nello heap

- SVM aggiorna il PC che passa a riga seguente

- SVM chiama run()

- SVM crea nuovo activation record per il run() contente la variabile locale counter

- Aggiorna il pc che diventa 4

- *Step 5-6-7* SVM esegue righe da 4 a 6 comprese (stampa variabili, incrementa e stampa)

- PC punta alla linea 7, counter vale 1

- SVM esegue return (elimina activation record di run dallo stack)

- Main esegue il return e elimina activation record del metodo main

-

SVM Thread States

Un programma concorrente ha più thread, quindi la SVM deve scegliere quale mandare in

esecuzione, la decisione dipende da vari fattori.

Programmazione Concorrente e Distribuita Page 5

Sleeping and Blocking

Un thread può essere sospeso per un certo periodo di tempo (Thread.sleep)

In questo caso, assume lo stato di sleeping o blocked

Sleep()

Non utilizza cicli del processore

- Metodo statico e mette in pausa il thread corrente

- Mentre è in sleep può essere interrotto da un thread o sollevata un eccezione

- ▪ Interrupt dovrebbe essere usata con wait, non con sleep

Creare un metodo che rallenti l'esecuzione di due thread non è una buona soluzione, si

- sprecano cicli di processore, inoltre si può avere ritardo rispetto al momento desiderato

(Busy Loop())

isAlive()

Testare se è vivo

- Quando viene chiamato start() il thread è alive

- Thread considerato alive finche non run() non ritorna

-

Join() Attende la terminazione del thread sul quale è chiamato

- Thread sul quale è chiamato join rimane bloccato in attesa che termini l'altro

-

Come stoppare un thread?

Non vi è un modo sicuro ed efficace per fermare un thread, esistevano vari metodi ma sono

- stati deprecati

Per fermare un thread la risposta definitiva è interrupt()

-

Interrupt()

Setta un flag di interruzione nel thread di destinazione e ritorna

- Thread non viene effettivamente interrotto

- Thread può controllare se flag è settato e nel caso uscire

- Metodi che mettono in pausa controllano il flag di interruzione prima dopo e durante

- Se flag è settato lancia un eccezione

- Thread da interrompere intercetta l'eccezione e dovrebbe terminare l'esecuzione

-

Problemi con Interrupt()

Interrupt() non funziona se il thread non esegue mai metodi di attesa (sleep, join)

- Thread devono cooperare per verificare il suo stato di interruzione

- ▪ isInterrupted(): controlla il flag senza resettarlo

▪ Thread.interrupted(): controlla il flag e se è settato lo resetta

Thread.yield()

Permette ad un thread di lasciare volontariamente il processore ad un altro thread

- Utile nel caso di un thread che non esegue spesso operazioni che lo mettano in attesa

- Si cede il contro allo scheduler che scegle un altro thread da mandare in esecuzione

- Quando si usa yield()?

- ▪ Quando non c'è preemption

▪ In casi particolari

Programmazione Concorrente e Distribuita Page 6

02 - Correctness

lunedì 7 maggio 2018 14:37

Il numero di diversi possibili percorsi di esecuzione di un programma concorrente è definito come:

NON-DETERMINISMO.

Il non-determinismo implica che testare un programma concorrente è solitamente difficile dato che

non è possibile determinare l'ordine assoluto dell'esecuzione delle istruzioni.

Questi problemi sono definiti come Race Condition: tutte quelle situazioni in cui thread diversi

operano su una risorsa comune ed in cui il risultato viene a dipendere dall'ordine in cui essi

effettuano le loro operazioni

Le Race Condition si possono verificare in due condizioni:

1. Una risorsa deve essere condivisa tra due thread

2. Deve esistere almeno un percorso di esecuzione tra i thread in cui una risorsa è condivisa in

modo non sicuro

Per dimostrare la correttezza di un programma concorrente esistono due modi:

• Dimostrare p

Anteprima
Vedrai una selezione di 7 pagine su 28
Programmazione concorrente e distribuita Pag. 1 Programmazione concorrente e distribuita Pag. 2
Anteprima di 7 pagg. su 28.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 6
Anteprima di 7 pagg. su 28.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 11
Anteprima di 7 pagg. su 28.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 16
Anteprima di 7 pagg. su 28.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 21
Anteprima di 7 pagg. su 28.
Scarica il documento per vederlo tutto.
Programmazione concorrente e distribuita Pag. 26
1 su 28
D/illustrazione/soddisfatti o rimborsati
Acquista con carta o PayPal
Scarica i documenti tutte le volte che vuoi
Dettagli
SSD
Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher biuzzo 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 dell' Insubria o del prof Lavazza Luigi.
Appunti correlati Invia appunti e guadagna

Domande e risposte

Hai bisogno di aiuto?
Chiedi alla community