Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Un thread (o processo leggero) una attivit, descritta da una Per un processo con pi thread di controllo, lo stato di
sequenza di istruzioni, che esegue all'interno del contesto di avanzamento della computazione di ogni thread dato da:
esecuzione di un programma. Un thread procede nella sua
valore del PC (prossima istruzione da eseguire)
esecuzione per portare a termine un certo obiettivo
parallelamente agli altri thread presenti. valore di SP/PSW e dei registri generali
I thread interagiscono tra loro poich possono scambiarsi dei contenuto dello Stack privato di quel thread (ovvero le variabili
messaggi e poich condividono risorse di sistema (come i file) e gli locali ad un metodo)
oggetti dello stesso programma. I thread competono nell'uso della
stato del thread: pronto, in esecuzione, bloccato
CPU e di altre risorse condivise (file o oggetti).
Sono invece comuni a tutti i thread:
I thread di uno stesso processo condividono dati e codice del
processo, ma lo stack di esecuzione ed il program counter sono stato dell!area testo e dati globali (gli attributi di una classe)
privati.
Stack del thread T1 Stack del thread T2 stato dei file aperti e delle strutture di IPC utilizzate
Esempio: un word processor multi-thread
Stack del thread T3
T
T dati 2
Legge i caratteri
da tastiera e li
Formatta
1 T visualizza
il testo
testo T2 disco
3 Processo P1 (Multithreaded)
Vantaggi :-) T1
il thread termina la sua esecuzione e passa nello stato di La classe Thread una classe non astratta che fornisce vari
stopped. metodi (es. start(), isAlive(), interrupt()) che
consentono di controllare l'esecuzione del thread.
I thread possono essere realizzati da librerie che eseguono in
modalit user Procedimento per creare un thread tramite sottoclasse di Thread:
il SO e lo scheduler non conoscono l!esistenza dei thread e 1. La sottoclasse di Thread deve implementare il metodo run()
gestiscono solo il processo
2. Bisogna creare una istanza della sottoclasse tramite new
lo scheduling viene effettuato dal supporto a run-time della
3. Si esegue il thread chiamando il metodo start() che a sua
libreria
volta richiama il metodo run()
Oppure, i thread possono essere realizzati all!interno del kernel
Creiamo una classe che eredita dalla classe Thread e che 1. Implementare in una classe R l'interfaccia Runnable (che
implementa il metodo run() implementa il metodo run())
ritorna la priorit del thread. blocca l'esecuzione del thread sul quale si invoca. Il thread
rimane in attesa di una operazione resume(). Non libera le
yield()
risorse impegnate. E' deprecato, poich pu determinare
metodo statico della classe Thread che ferma situazioni di blocco critico (deadlock).
momentaneamente l!esecuzione del thread corrente per
permettere ad un altro thread di eseguire.
ThreadJavaE.Tramontana-25-11-05 7/18 ThreadJavaE.Tramontana-25-11-05 8/18
M e t o d i d e l l a c l a s s e Thread - 3 Sincronizzazione
interrupt() Differenti thread della stessa applicazione condividono lo stesso
spazio di memoria. E' quindi possibile che pi thread accedano alla
permette di interrompere l'esecuzione del thread sul quale si
stessa sezione di codice o allo stesso dato.
invoca, solo quando lo stato dell'oggetto lo consente, cio
quando non in esecuzione, ma in attesa di un evento. Ci La durata e l'ordine di esecuzione dei thread non predicibile. Non
consente (a differenza del metodo stop()) di mantenere lo possiamo stabilire quando lo scheduler del SO interromper
stato dell'oggetto consistente. l'esecuzione di un thread per eseguirne un altro.
Thread currentThread() Quando pi di una attivit esegue, l'esecuzione necessariamente
non-deterministica e la comprensione del programma non data
un metodo statico della classe Thread che restituisce un
dalla semplice lettura sequenziale del codice.
identificativo del thread che sta correntemente eseguendo.
Per esempio, una variabile che assegnata con un valore in una
toString()
istruzione di programma, pu avere un differente valore nel
restituisce una rappresentazione del thread, che include nome, momento in cui la linea successiva eseguita (a causa
priorit e gruppo. dell'esecuzione di attivit concorrenti).
L'uso di stop() e suspend() sconsigliata poich bloccano Esempio:
bruscamente l'esecuzione di un thread. Possono quindi generare thread_1 thread_2 num
problemi allo stato dell'oggetto, poich una azione atomica
num=0; 0
(indivisibile) viene interrotta. Inoltre, con suspend(), tutte le
risorse acquisite non sono rilasciate quando il thread bloccato e genera(); 0
possono rimanere inutilizzabili indefinitamente. num++; 1
consuma(); 1
num--; 0
E' meglio usare dei metodi per la sincronizzazione fra thread:
wait(), notify() e notifyAll() if (num > 0) notifica(); 0
Quando un thread tenta di accedere ad un oggetto istanza di In Java ogni oggetto potenzialmente un monitor. La classe
questa classe, acquisisce implicitamente il lock (se nessun thread Object mette quindi a disposizione i metodi di sincronizzazione:
sta eseguendo all'interno dello stesso oggetto). wait(), notify() e notifyAll(). Esse possono essere
invocate solo dopo che stato acquisito un lock, cio all'interno di
Il thread che detiene il lock per un oggetto di questo tipo pu
un blocco o metodo synchronized.
eseguire liberamente (senza alcun test) tutti i metodi dell'oggetto.
wait()
I thread che dopo tentano di accedere allo stesso oggetto verranno
sospesi, e risvegliati quando il thread che all'interno finisce blocca l'esecuzione del thread invocante fino a che un altro
l'esecuzione del metodo. In pratica, il thread che era all'interno thread invoca una notify() sull'oggetto. Si fa sempre dopo
rilascia automaticamente il lock. aver testato una condizione (ed in un ciclo, per essere sicuri
che al risveglio la condizione verificata).
Un metodo synchronized non interrotto, cio viene eseguito in
while (! condition) // se non pu procedere
modo atomico (ok, il thread che lo esegue pu essere interrotto). this.wait(); // aspetta una notifica
Se sono presenti dei metodi non synchronized all'interno della
Il thread invocante viene bloccato, il lock sull'oggetto
classe, su questi non viene acquisito il lock all'ingresso. rilasciato automaticamente.
L'uso di synchronized introduce un overhead: il tempo
I lock su altri oggetti sono mantenuti (bisogna quindi fare
necessario per cominciare ad eseguire il metodo maggiore di attenzione a possibili deadlock).
quello di un metodo non synchronized (per alcune
implementazioni costa 4 volte in pi). Un oggetto con metodi synchronized gestisce di per s 2
code:
Ogni volta che usiamo metodi synchronized riduciamo il
parallelismo possibile all'interno del programma e potenzialmente una coda di lock, per i thread a cui l!accesso escluso,
costringiamo alcuni thread ad attendere. una coda di wait per le condizioni di attesa.
L'uso di synchronized ci protegge da eventuali interferenze
Un thread pu essere in una sola delle due code.
durante l'esecuzione del codice ed quindi utile per garantire la
correttezza, ma richiede una certa attenzione per prevenire ritardi e La variante wait(long timeout) blocca il thread per al
deadlock. massimo timeout millisecondi (se timeout > 0)
notifyAll()
In questo caso posso sempre avere un singola classe con tutte le ThreadGroup mytg = new ThreadGroup(mio gruppo);
Thread myt = new Thread(mytg, mio t);
funzionalit, ma pi lock che regolano l'accesso dei thread.
L'implementazione pu essere ottenuta, per esempio, con l'uso di
synchronized su un blocco di codice e non sui metodi della
classe.
Coppie di lock, per lettura e per scrittura: posso identificare quali
operazioni sono in lettura (non modificano lo stato) e quali in
scrittura e consentire pi lettori contemporaneamente, ma un solo
scrittore alla volta.