1. Corso
Programmazione Java Avanzata
Modulo 17: MultiThreading
Leggi il programma completo del corso
www.javaportal.it | www.k-tech.it corsi@k-tech.it
2. Agenda
............
Cap 12 - Cache
Cap 13 - Logging
Cap 14 - SWING/AWT
Cap 15 -JVM
Cap 16 - Profiling e Tuning
►Cap 17 - MultiThreading◄
Cap 18 - Grid Computing
www.javaportal.it | www.k-tech.it corsi@k-tech.it 2
3. Definizioni di base
● PROCESSO – Programma in esecuzione
● THREAD – Processo leggero
Thread 1 Thread 2
Processo
www.javaportal.it | www.k-tech.it corsi@k-tech.it 3
4. Definizioni di base
MULTI-TASK: Un sistema operativo multitask permette di eseguire più
programmi concorrentemente.
MULTI-THREAD: Il multithreading è una tecnica che permette di avere più flussi
di esecuzione contemporanei (thread) in uno stesso processo.
SCHEDULER: Lo scheduler si occupa di fare avanzare un processo
interrompendone temporaneamente un altro, realizzando così un cambiamento
di contesto (context switch).
preemption
Esegue P1 (context-switch)
P1
P2
Esegue P3
P3
time-slice
www.javaportal.it | www.k-tech.it corsi@k-tech.it 4
5. Perché MultiThread?
Generalmente si creano applicazioni multithread per questioni di
Performance:
● non si deve generare codice con scadenti prestazioni dipendenti
da una cattiva gestione della sincronizzazione;
● ma non si deve eliminare la sincronizzazione in virtù di una
miglior velocità del sistema.
First make it work, then make it fast!
www.javaportal.it | www.k-tech.it corsi@k-tech.it 5
6. Creare Thread in Java
Ci sono due possibilità per creare un thread in Java:
1. come oggetti di sottoclassi della classe Thread;
2. come oggetti di classi che implementano l’interfaccia Runnable.
Sia la classe Thread che l’interfaccia Runnable appartengono al
package java.lang
In entrambi i casi, un thread esegue l'algoritmo implementato nel
suo metodo run() e va in esecuzione concorrente con gli altri
thread esistenti.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 6
7. Utilizzo dei Thread
Le seguenti operazioni di base consentono di controllare l’esecuzione dei
thread:
t.suspend(); // sospende l’esecuzione di t - deprecated
t.resume(); // fa riprendere l’esecuzione di t - deprecated
t.stop(); // forza la terminazione di t - deprecated
t.join(); // consente di attendere sino ala terminazione di t
yield(); // il thread corrente cede il controllo ad altri
ATTENZIONE:
I metodi stop(), suspend() e resume() rappresentano azioni “brutali” sul ciclo
di vita di un thread => rischio di determinare blocco critico (deadlock)!
Primitive di sincronizzazione:
wait(); // pone il thread in attesa del verificarsi di una
// condizione
notify(); // segnala il cambiamento di una condizione
// (es. rilasciata una risorsa condivisa )
notifyAll(); // come sopra ma sveglio tutti i thread in attesa
www.javaportal.it | www.k-tech.it corsi@k-tech.it 7
8. Priorità dei Thread
Ai thread è possibile assegnare una priorità:
t.setPriority(thread_priority);
t.getPriority();
Le priorità possono variare in un intervallo (tipo 1-10), identificato
dalle costanti Thread.MIN_PRIORITY e Thread.MAX_PRIORITY.
Come default i thread prendono tutti la stessa priorità, ovvero:
Thread.NORM_PRIORITY.
Lo scheduler della JVM dispaccia sulla CPU uno dei thread con la
priorità più alta che si trova nello stato ready-to-run.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 8
9. Ciclo di vita dei Thread
Waiting/
blocking
New Runnable Running Dead
www.javaportal.it | www.k-tech.it corsi@k-tech.it 9
10. Verifica dell’ambiente MultiThread...
Si consideri la seguente classe che definisce un thread corridore:
Runner.java
class Runner extends Thread {
public Runner(String nome){ super(nome); }
public void run(){
for(int tick=0;tick<400000;tick++)
if(tick%5000==0)
System.out.println(”Runner: ”+getName()+“ tick: “+tick);
}
}
Ed il seguente programma che crea e attiva due corridori:
Runner.java
public class TestYourJavaRuntimeSystem {
public static void main(String [] args){
Runner r1 = new Runner(“r1”);
Runner r2 = new Runner(“r2”);
r1.start();
r2.start();
}
}
www.javaportal.it | www.k-tech.it corsi@k-tech.it 10
11. ...Verifica dell’ambiente MultiThread
Se l’ambiente multithread disponibile non è time-sliced, un possibile output
potrebbe essere:
Runer: r1 tick: 0
Runer: r1 tick: 5000
Runer: r1 tick: 10000
…
Runer: r1 tick: 395000
Runer: r2 tick: 0
Runer: r2 tick: 5000
Runer: r2 tick: 10000
…
Runer: r2 tick: 395000
Ossia l’esecuzione di r2 inizia soltanto dopo che l’esecuzione di r1 è terminata.
Se invece il sistema è pre-emptive con time-slicing, ogni thread rimane in
esecuzione per un quanto di tempo. Quindi viene spodestato dalla CPU, da
parte dello scheduler, che lancia l’esecuzione dell’altro thread. L’output è
costituito da scritte, casualmente alternate, generate dai due thread.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 11
12. Meccanismi di sincronizzazione...
Normalmente i thread di un’applicazione non sono indipendenti (come i
corridori). Piuttosto essi collaborano al raggiungimento di un obiettivo
globale e necessitano di comunicazione e cooperazione per evitare
l’insorgere di race condition (condizioni di corsa).
v 2
P1 P2
MOVE AX,v : : MOVE AX,v
ADD AX,2 v = v +1 INC AX
v = v +2
MOVE v,AX MOVE v,AX
: :
Fondamentali sono a questo proposito le operazioni di sincronizzazione
nell’accesso a risorse condivise.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 12
13. ...Meccanismi di sincronizzazione...
Possibile scheduling:
P1 P2
AX v
? 2
MOVE AX,v 2 2
ADD AX,2 4 2
context switch
MOVE AX,v 2 2
INC AX 3 2
MOVE v,AX 3 3
context switch
3 3
MOVE v,AX
Al termine dell’esecuzione dei due processi, la variabile v avrà come contenuto
3 e non 5 come ci saremmo aspettati! => Dobbiamo mettere un lucchetto su v,
ovvero eseguire in modo atomico le istruzioni che la manipolano definendo delle
sezioni critiche!
www.javaportal.it | www.k-tech.it corsi@k-tech.it 13
14. ...Meccanismi di sincronizzazione...
Una classe è detta thread-safe se può essere acceduta
contemporaneamente da un insieme di thread, escludendo il rischio di
race-condition.
In Java la sincronizzazione è essenzialmente assicurata dall’adozione di
un meccanismo di monitoraggio. Ciascuna istanza di una classe
thread-safe ha associato un monitor e i metodi della classe possono
essere eseguiti in mutua esclusione.
La sintassi di una generica classe thread-safe:
ThreadSafe.java
public class ThreadSafe … {
public syncronized void method1(){ // sezione critica }
public syncronized void method2(){ // sezione critica }
}
www.javaportal.it | www.k-tech.it corsi@k-tech.it 14
15. ...Meccanismi di sincronizzazione
Si garantisce l'accesso ai dati interni dell'oggetto ad un solo thread per
volta.
Un metodo con molte istruzioni necessita di un tempo di esecuzione
lungo, questo determina una attesa prolungata da parte degli altri thread.
Java offre anche il blocco sincronizzato per restringere l’estensione della
sezione critica:
synchronized(oggetto){
// sezione critica
}
L’oggetto denota l’istanza su cui un thread pone un lucchetto.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 15
16. Produttore Consumatore…
Il problema Produttore Consumatore è un classico problema
di IPC (Inter-Process Communication) della letteratura tecnica.
Analizziamo la variante con un solo produttore ed un solo consumatore:
Produttore Buffer Consumatore
● il produttore alterna le fasi di produzione e deposito;
● il consumatore alterna le fasi di prelievo e consumo;
● il buffer fa da “tampone”;
● il buffer è una risorsa condivisa => operazioni su buffer sincronizzate.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 16
17. …Produttore Consumatore…
BufferLimitato.java
class BufferLimitato {
private int n;
private int[] buffer;
private int in, out, count;
public BufferLimitato( int n ){
this.n=n; buffer = new int[n]; in=0; out=0; count=0;
}
public synchronized int get() {
if( count==0 )
try { wait(); } catch (InterruptedException ignored) {}
int ans = buffer[out]; out = (out+1)%n; count--;
notify();
return ans;
}
public synchronized void put( int value ) {
if( count==n )
try { wait(); } catch (InterruptedException ignored) {}
buffer[in] = value; in = (in+1)%n; count++;
notify();
}
}
www.javaportal.it | www.k-tech.it corsi@k-tech.it 17
20. …Produttore Consumatore…
Si è fatto uso delle primitive wait() e notify() definite da Object.
L’operazione wait() pone un thread in attesa al verificarsi di una condizione.
L’operazione notify() segnala che una condizione è cambiata e che dunque
l’altro thread in attesa può riprendere l’esecuzione.
OSSERVAZIONE: Ma se i Produttori e/o i Consumatori sono più di uno?
BufferLimitato.java
class BufferLimitato {
//…
public synchronized int get() {
while( count==0 )
//…
notifyAll(); return ans;
}
public synchronized void put( int value ) {
while( count==n )
//…
notifyAll();
}
}
www.javaportal.it | www.k-tech.it corsi@k-tech.it 20
22. Osservazioni conclusive
E’ indispensabile ricorrere a strategie di sincronizzazione tra thread che
condividono risorse, in quanto potrebbero nascere problematiche piuttosto gravi:
DEADLOCK
Può succedere che un gruppo di thread non possa procedere con l'esecuzione
in quanto ognuno di essi è in attesa di una risorsa bloccata da un altro thread
del gruppo. Ad esempio:
● Il thread 1 ha il lock su A ed e in attesa del lock di B.
● Il thread 2 ha il lock su B ed e in attesa del lock di A.
STARVATION
Può succedere che un thread non avanzi perché le risorse necessarie sono
sempre ipotecate da altri.
www.javaportal.it | www.k-tech.it corsi@k-tech.it 22
23. Domande
● Quanti e quali sono le alternative per creare thread in Java?
● Un thread a cui si invia un messaggio di start() in quale stato si
trova?
● Perchè il metodo stop() è deprecato?
● Quale problematica è più grave, il deadlock o la starvation?
● Chi consente il passaggio ad un thread dallo stato Runnable
allo stato Running?
www.javaportal.it | www.k-tech.it corsi@k-tech.it 23
24. Riferimenti
● Core Java 2: Volume I: Fondamenti
Cay S. Horstmann, Gary Cornell, 2005
● Core Java 2: Volume II: Tecniche Avanzate
Cay S. Horstmann, Gary Cornell, 2005
● Java Threads
Scott Oaks, Henry Wong 1999
● Database Programming with JDBC and Java
George Reese, 2001
● Java Database Programming Bibble
John O'Donahue, 1999
● MySQL and Java Developer’s Guide
Mark Matthews, Jim Cole, Joseph D. Gradecki, 2003
www.javaportal.it | www.k-tech.it corsi@k-tech.it 24
25. BREAK
Dopo la pausa:
Grid Computing
Leggi il programma completo del corso
www.javaportal.it | www.k-tech.it corsi@k-tech.it 25