Priorità e Sincronizzazione tra
Threads
Priorità e preemption
• Java non garantisce la preemption
• Lo scheduling avviene in base all’algortimo
Highest Priority First
• Un thread interrompe l’esecuzione se:
– Esce dal proprio metodo run()
– Si sospende invocando sleep(), wait() oppure è in
attesa di I/O
– Cede la CPU invocando yield()
– Entra nel sistema un thread a priorità maggiore
sleep((long)(Math.random() * 1000));
Se il thread etra nello stato Not Runnable, vi è sempre una specifica modalità per
tornare
nello entra
stato nello
Runnable
Un thread
stato :Not Runnable se uno dei seguenti eventi si verifica:
• Se
il thread sleep
è statoè disposto
•Il metodo
invocato.nello stato di sleep(), dopo che un determinato
numero
di millisecondi
è terminato.
•Il thread
chiama il metodo
wait in attesa che una specifica condizione sia
• Se
il
thread
è
in
stato
di
wait(),
si attende che un altro oggetto notifichi la
soddisfatta.
condizione
thread inin
attesa
•Il thread al
è bloccato
I/O. con notify() o notifyAll(). Altri dettagli in
Synchronizing Threads.
• Se un thread è bloccato in I/O, occorre attendere che l’I/O completi
Un programma non ferma un thread come avviene con un Applet attraverso la
chiamata di un metodo. Un thread provoca la propria morte attraverso la
terminazione naturale del metodo run.
public void run() {
Causa
pausa
forla(int
i = 0; temporanea
i < 10; i++) { del thread correntemente in esecuzione e
Metodo
isAlive
permette
ad altri thread di+essere
eseguiti.
System.out.println(i
" + getName());
Il metodo
isAlive restituisce" true
se il thread è in stato Runnable o Not
try {
Runnable.sleep((long)(Math.random()
Se il metodo isAlive restituisce
false, il thread è un nuovo thread
* 1000));
oppure }ècatch
morto.
Non è possibile distinguire
tra un nuovo thread e un thread
(InterruptedException
e) {}
morto} e tra un thread Runnable e un thread Not Runnable.
System.out.println("DONE! " + getName());
}
Thread Priority
Thread 1
priority
Thread 2
Thread 1
Thread 2
1
CPU
PREEMPTION
fixed priority scheduling.
Scheduler
 esegue il thread con più
alta priorità
Quando
thread si
• Un thread
a piùil alta
ferma,
yields,
o diventa
priorità
diventa
runnable.
Not Runnable,
un thread
•Il thread
yields, oppure
il a
bassarun
priorità
inizierà
suopiù
metodo
termina
l’esecuzione
•Su sistemi
che
Se due
thread con
supportano
partizione
di
stessa
priorità
sono
in
tempo, la frazione di
attesa
di essere
eseguiti,
tempo
allocata
è
lo scheduler li esegue con
terminata
politica round-robin.
• The Java runtime will not preempt the currently running thread for
another thread of the same priority. In other words, the Java runtime does
not time-slice. However, the system implementation of threads underlying
the Java Thread class may support time-slicing.
Do not write code that relies on time-slicing.
• In addition, a given thread may, at any time, give up its right to execute
by calling the yield method. Threads can only yield the CPU to other
threads of the same priority--attempts to yield to a lower priority thread are
As you can imagine, writing CPU-intensive code can
ignored.
have negative repercussions on other threads
runningthreads
in the same
In general,
youpriority,
should the
• When all the runnable
in theprocess.
system have
the same
to next
writethread
"well-behaved"
voluntarily
scheduler choosestrythe
to run in athreads
simple,that
non-preemptive,
relinquish
the CPU periodically and give other
round-robin scheduling
order.
threads an opportunity to run. In particular, you
should never write Java code that relies on timesharing--this will practically guarantee that your
program will give different results on different
computer systems.
Sincronizzazione
Balance = 15;
if (Balance – 10 >= 0)
Thread1
If( … )
Balance -= 10;
Thread2
If( … )
Balance -=10
Balance -=10
Balance
15
15
5
-5 !!
Sincronizzazione/1
1. Uso di blocchi synchronized
2. Uso dei metodi wait() e notify()
(appartengono alla classe Object)
• Noi vediamo synchronized
Sincronizzazione/2
• E’ necessario che un solo thread alla
volta possa eseguire il blocco di codice
• Ciò può essere dichiarato con la sintassi
seguente:
synchronized ((Integer) Balance) {
if (Balance – 10 >= 0)
}
Balance -= 10;
Sincronizzazione/3
• Il thread che esegue per primo
l’istruzione synchronized acquisisce il
controllo (lock) dell’oggetto Balance
• Il lock è rilasciato all’uscita del blocco
• Nessun altro thread può eseguire
istruzioni del blocco senza aver prima
acquisito il lock sull’oggetto
Sincronizzazione/4
• Si possono dichiarare metodi synchronized (anche statici)
class myClass {
private int myVar;
public synchronized void myMethod(int newVal) {
myVar = newVal;
}
......
• Solo un thread alla volta può modificare myVar (quello che
ottiene il lock sull’oggetto di tipo myClass)
Thread Sincronizzati
Thread separati devono considerare la condivisione di dati e
lo stato di attività degli altri Threads.
Occorre comunque sincronizzare threads che
condividono una risorsa
Thread A
Thread B
write
read
Produttore/Consumatore
sleep(random)
PRODUCER
i
k
Il consumatore non deve acedere il
cubbyhole quando viene modificato dal
produttore, e il produttore non deve
modificarlo quando il consumatore sta
accedendo  get, put methods
synchronized.
CONSUMER
i
i
cubbyhole.get()
cubbyhole.put(i)
cubbyhole
synchronized
Skeleton
public class CubbyHole {
private int contents;
private boolean available = false;
public synchronized int get() { ... }
public synchronized void put(int value) { ... }
}
public synchronized void put(int value) {
// CubbyHole
locked by the int
Producer
public synchronized
get() {
..
// CubbyHole locked by the Consumer
// CubbyHole unlocked
by the Producer
...
}
// CubbyHole unlocked by the Consumer
}
Il sistema associa un unico lucchetto ad ogni istanza di CubbyHole
(compresa quella condivisa dal produttore e dal consumatore). Quando
il controllo invoca un metodo sincronizzato, il thread che ha chiamato
questo metodo blocca l’oggetto su cui il metodo è stato invocato. Gli
altri threads non possono chiamare un metodo sincronizzato sullo
stesso oggetto finchè l’oggetto non è rilasciato.
i
PRODUCER
put
i
L’acquisizione ed il rilascio di un lucchetto è realizzato
automaticamente ed in modo atomico dal sistema runtime di Java.
Questo evita corse critiche ell’implementazione dei threads e
l’integrità dei dati.
La sincronizzazione non conclude la questione. Due thread devono
anche essere in grado di notificare reciprocamente l’avvenuto
svolgimento di un compito.
public synchronized int get() {
if (available == true) {
available = false;
return contents;
}
}
Cosa succede se il produttore
non ha disposto alcun oggetto
nel Cubbyhole e
available non è true?
get non fa nulla
public synchronized void put(int value) {
if (available == false) {
available = true;
contents = value;
}
}
Se il produttore invoca
put prima che il consumatore
ottenga il valore, non si ha
nessun valore nel Cubbyhole.
WAIT & NOTIFYALL
private boolean available = false
public synchronized int get() {
while (available == false) {
try {
// wait for Producer to put value
wait();
} catch (InterruptedException e) { }
}
available = false;
// notify Producer that value has been retrieved
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
// wait for Consumer to get value
wait();
} catch (InterruptedException e) { }
}
contents = value;
available = true;
// notify Consumer that value has been set
notifyAll();
}
Ilmetodo notifyAll risveglia tutti
i threads in attesa sull’oggetto
in questione. I threads
notificati competono per il
lock.Il Un
thread
otterrà
metodo
wait
l’oggetto,
rilasciamentre
il lock gli altri
torneranno
stato di attesa.
ottenutoindal
Il consumatore
esce
La classe
Object anche
consumatore
sul
dalloun
stato
di wait,
definisce
metodo
notify,
CubbyHole
e
availablearbitrariamente
è ora true, il
che quindi
risveglia
attende la
loop
termina
ed il
une notifica
dei
thread
del in attesa
metodo get restituisce il
sull’oggetto.
produttore
valoreQuando
nel Cubbyhole.
il produttore
wait
dispone qualcosa nel
CubbyHole, notifica il
consumatore
atraverso notifyAll
Il produttore può
ottenere il lock e
qundi aggiornare il
CubbyHole
Scarica

Diapositiva 1