Presentazione tre geni della tecnologia informatica
Lezione 2: I thread
1. Lezione 2: I thread
Corso di Programmazione in Rete
Laurea Magistrale in Ing. Informatica
Università degli Studi di Salerno
1
2. Outline
✦ Introduzione ai thread
✦ I thread in Java
✦ La sincronizzazione
2
3. Introduzione ai thread
✦ Sequenza statica = sequenza delle
istruzioni nel testo del programma
✦ Sequenza dinamica = sequenza in cui le
istruzioni sono eseguite durante una
particolare esecuzione del programma
✦ Tradizionalmente, ad ogni esecuzione è
associata un’unica sequenza statica detta
anche flusso di esecuzione o thread of
execution
3
4. Multi-threading
✦ Nei moderni sistemi operativi un
programma può attivare più flussi di
esecuzione (thread) che procedono
simultaneamente
✦ I programmi che sfruttano questa
possibilità sono detti multi-threaded
✦ Nota:
• Multitasking = più programmi attivi
contemporaneamente
• Multithreading = più thread attivi nello stesso
programma
4
5. Multi-threading
✦ In un programma a singolo thread:
Operazione A {
istruzione 1
istruzione 2
... ...
OperazioneA(); }
OperazioneB();
...
Operazione B {
istruzione 1
L'operazione A deve essere istruzione 2
completata prima che il programma ...
possa cominciare l'operazione B }
5
6. Multi-threading
✦ In un programma multi-threaded
Operazione A {
... istruzione 1
nuovo thread { istruzione 2
OperazioneA(); ...
} }
OperazioneB();
...
Operazione B {
istruzione 1
L’operazione A è eseguita in un istruzione 2
thread separato da quello ...
principale; B comincia prima che A }
sia terminata
(A e B sono eseguite “in parallelo”)
6
7. Multi-threading
✦ Se il computer ha più processori:
esecuzione parallela dei thread
✦ Se il computer ha un solo processore (o
un numero di processori inferiore al
numero di thread): esecuzione
concorrente (time sharing)
esecuzione parallela operazione A
operazione B
esecuzione operazione A
concorrente
operazione B
tempo
7
8. Vantaggi
✦ Sfruttare il parallelismo quando
disponibile
✦ Operazioni lunghe in “background” senza
bloccare il programma
✦ Alcuni programmi devono comunque
gestire più richieste contemporaneamente
(es. web server)
8
9. Svantaggi
✦ Ogni thread richiede memoria per lo stack
e altre risorse
✦ Il passaggio del processore da un thread
all’altro (context switch) non è
un’operazione istantanea
Quindi: non è conveniente avere un
numero molto elevato di thread
9
10. Sincronizzazione
✦ I thread di un programma hanno tutti
accesso alle risorse del programma e
possono modificarne lo stato
✦ La modifica dello stato di una struttura
dati simultaneamente da parte di più
thread può portare la struttura dati in uno
stato inconsistente
✦ È necessario un coordinamento tra i
thread che devono accedere a una stessa
struttura dati (sincronizzazione)
10
11. Sincronizzazione
✦ Esempio: supponiamo di avere una
variabile condivisa SALDO che contenga il
saldo di un conto corrente
PRELIEVO: VERSAMENTO:
x ← SALDO y ← SALDO
x ← x-50 y ← y+75
SALDO ← x SALDO ← y
✦ Cosa succede se le due operazioni sono
eseguite in due thread attivi
simultaneamente?
11
12. I thread in Java
✦ In Java è possibile creare un nuovo
thread usando la classe Thread
✦ Occorre associare il thread alle operazioni
che deve svolgere
• Creazione di una sottoclasse di Thread
• Creazione di un oggetto che implementi
l’interfaccia Runnable, da passare al costruttore di
Thread
✦ Il thread deve essere avviato con il
metodo start
12
13. Thread in Java
✦ Esempio
public class HelloThread extends Thread {
public void run() {
int i;
for(i=0; i<100; i++)
System.out.println("Hello, world");
}
}
public class TestHello1 {
public static void main(String[] args) {
// Creazione e avvio di un nuovo thread
Thread t=new HelloThread();
t.start();
// Simultaneamente, nel thread del main...
int i;
for(i=0; i<100; i++)
System.out.println("Salve, mondo");
}
}
13
14. Thread in Java
✦ Esempio
public class HelloPrinter implements Runnable {
public void run() {
int i;
for(i=0; i<100; i++)
System.out.println("Hello, world");
}
}
public class TestHello2 {
public static void main(String[] args) {
// Creazione e avvio di un nuovo thread
HelloPrinter hello=new HelloPrinter();
Thread t=new Thread(hello);
t.start();
// Simultaneamente, nel thread del main...
int i;
for(i=0; i<100; i++)
System.out.println("Salve, mondo");
}
}
14
15. Daemon thread
✦ Un programma Java termina quando tutti
i suoi thread sono terminati
✦ È possibile dichiarare un thread come “di
servizio” (daemon thread) in modo che il
programma termini quando sono rimasti
attivi solo i thread di servizio
• A tale scopo si usa il metodo:
void setDaemon(boolean isDaemon)
della classe Thread prima di chiamare start()
15
16. Sincronizzazione in Java
✦ Ogni oggetto Java contiene una struttura
dati detta mutex che consente di
garantire che l’accesso all’oggetto venga
effettuato da un solo thread per volta
(“mutua esclusione”)
✦ Combinando l’uso del mutex con
l’incapsulamento il programmatore può
gestire il problema della sincronizzazione
16
17. Synchronized
✦ Il mutex di un oggetto si utilizza tramite il
costrutto synchronized, la cui sintassi è:
synchronized (obj) {
istruzione ...
}
17
18. Synchronized
✦ Il thread che esegue synchronized
“acquisisce” il mutex dell’oggetto indicato
per tutta la durata del blocco di istruzioni
specificato
✦ Un solo thread alla volta può acquisire un
certo mutex
✦ Se un altro thread prova ad acquisire un
mutex già impegnato da un altro thread,
viene messo in attesa fino a quando
l’altro thread non rilascia il mutex
18
19. Synchronized
✦ Esempio
public class ContoCorrente {
private double saldo;
public ContoCorrente(double saldoIniziale) {
saldo=saldoIniziale;
}
public double getSaldo() {
synchronized (this) {
return saldo;
}
}
public void versa(double x) {
synchronized (this) {
saldo+=x;
}
}
}
19
20. Synchronized
✦ Spesso occorre rendere synchronized
l’intero corpo di un metodo usando il
mutex dell’oggetto corrente (this)
✦ Sintassi semplificata: premettere la
parola chiave synchronized
all’intestazione del metodo
20
21. Synchronized
✦ Esempio
public class ContoCorrente {
private double saldo;
public ContoCorrente(double saldoIniziale) {
saldo=saldoIniziale;
}
public synchronized double getSaldo() {
return saldo;
}
public synchronized void versa(double x) {
saldo+=x;
}
}
21