Esercizi thread interference
1) (1 punto) Quale metodo viene invocato su un oggetto di tipo thread per mandare un thread in esecuzione?
2) (1 punto) Qual'è il metodo dell'interfaccia Runnable
che deve essere implementato per creare una classe di tipo Runnable
?
3) (1 punto) Scrivete il codice di un thread che scrive 5 volte "CIAO", compresa la parte per lanciare il thread in esecuzione.
4) (3 punti) Il metodo interrupt()
invocato su una variabile di tipo thread che cosa genera se il thread sta eseguendo la sleep()
?
5) (3 punti) All'interno di un thread t1 viene fatto partire un thread t2.
Quale metodo va invocato su t2 per far si che t1 interrompa la sua esecuzione finché t2 non sia terminato?
6) (2 punti) L'accesso a una variabile condivisa da parte di due o più thread si chiama:
- deadlock
- sequenza critica
- InterruptedException
7) (1 punti) Quali sono le due tecniche di base utilizzate da Java per evitare che l'accesso a una variabile condivisa da parte di più thread dia risultati inconsistenti?
8) (2 punti) Abbiamo una variabile di tipo Contatore con un metodo per decrementare il valore, decrement() e un metodo che restituisce il valore getValue();
Qui sotto l'esempio di come si deve comportare un oggetto di tipo Contatore.
Implementare la classe Contatore scrivendo il codice, in modo che l'accesso da parte di più thread non crei una sequenza critica nel caso due thread eseguano contemporaneamente l'operazione di decrement().
RISPOSTA:
Una semplice classe Contatore che implementa i due metodi come esposti sopra potrebbe essere:
Ora per rendere sicura la sezione critica del metodo decrement() o lo rendo synchronized o in modo equivalente creo un blocco synchronized sull'oggetto (con this). Sotto le due versioni equivalenti.
Anche il metodo getValue() è stato sincronizzato per garantire la relazione di happends-before su variabili condivisa. Vedi: Memory Consistency Properties.
9) (2 punti) Implementare una classe Contatore come quella precedente ma che permetta a due thread t1 e t2 a uno di accedere al metodo increment() e all’altro a quello getValue() contemporaneamente, mentre non possono accedere contemporaneamente a increment() o a getValue().
RISPOSTA:
La soluzione è avere due oggetti distinti su cui ottenere il lock utilizzando i blocchi synchonized:
In questo modo un thread può acquisire il lock su obj1 per eseguire il metodo decrement()
e contemporaneamente un altro thread può acquisire il lock su obj2 per eseguire il metodo getValue()
.
Vedi:
10) (4 punti) E’ data la classe Decrementer di tipo Thread
che agisce su una variabile di tipo Contatore e decrementa il contatore finché non arriva a 0 e quindi termina l'esecuzione del thread (codice qui sotto).
Immaginate due thread t1 e t2 di tipo Decrementer vengono mandati in esecuzione contemporaneamente passandogli una stessa variabile di tipo Contatore.
Domanda 1: Con quale flusso di esecuzione potrebbe succedere che i due thread, t1 e t2, non terminino non arrivando mai alla condizione d'uscita?
Domanda 2: Come si potrebbe cambiare il codice per far si che invece i due thread terminino?
SOLUZIONE
Last updated