Il 0% ha trovato utile questo documento (0 voti)
15 visualizzazioni44 pagine

18 10 24 CallableMonitor

Caricato da

sabry.minali
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
15 visualizzazioni44 pagine

18 10 24 CallableMonitor

Caricato da

sabry.minali
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Sei sulla pagina 1/ 44

Università degli Studi di Pisa

Dipartimento di Informatica

Reti e Laboratorio 3
Modulo Laboratorio 3
AA. 2024-2025
docente: Laura Ricci
[email protected]
Lezione 5
Callable, Monitor
18/10/2024

Dipartimento di Informatica 1
Università degli studi di Pisa Callable, Monitor Laura Ricci
THREAD STATES AND JAVA OPERATIONS: RECAP


yield segnala allo schedulatore di portare il thread corrente in stato di
Runnable e di schedulare un altro thread

sleep pone il thread nello stato di bloccato per un certo intervallo di tempo

wait-notify la vedremo più avanti nella lezione

join permette a un thread di attendere la terminazione di un altro thread
Dipartimento di Informatica 2
Università degli studi di Pisa Callable, Monitor Laura Ricci
THREAD CHE RESTITUISCONO RISULTATI
• un oggetto di tipo Runnable

incapsula un'attività che viene eseguita in modo asincrono

il metodo run è un metodo asincrono, senza parametri e che non
restituisce un valore di ritorno
• Interface Callable: consente di definire un task che può restituire un
risultato, in modo asincrono, e sollevare eccezioni

come “accedere” al risultato, in modo asincrono?

Future interface: contiene metodi per reperire, in modo asincrono, il
risultato di una computazione asincrona. cioè

per controllare se la computazione è terminata

per attendere la terminazione di una computazione (eventualmente per
un tempo limitato)

per cancellare una computazione, .....
• la classe FutureTask fornisce una implementazione della interfaccia Future.

Dipartimento di Informatica 3
Università degli studi di Pisa Callable, Monitor Laura Ricci
L'INTERFACCIA CALLABLE
public interface Callable <V>
{ V call() throws Exception;}
• contiene il solo metodo call(), analogo al metodo run() dell'interfaccia
Runnable
• il codice del task è implementato nel metodo call()
• a differenza del metodo run(), il metodo call() può

restituire un valore

sollevare eccezioni
• il parametro di tipo <V> indica il tipo del valore restituito

Callable <Integer> rappresenta una elaborazione asincrona che
restituisce un valore di tipo Integer

occorre utilizzare il metodo submit(), quando si sottomette la Callable ad un
threadpool, invece della execute()

Dipartimento di Informatica 4
Università degli studi di Pisa Callable, Monitor Laura Ricci
DIVIDE ET IMPERA CON MULTITHREADING
calcolare la somma di tutti i numeri da 1 a n
• soluzione sequenziale: loop che itera da 1 a 100 e calcola la somma
• seguendo il pattern divide and conquer :

individuare sottointervalli dell'intervallo 1-100

creare un task diverso per ogni intervallo: calcola la somma per
quell'intervallo

sottomettere i task ad un threadpool, calcolare le somme parziali in modo
concorrente

raccogliere le somme parziali per calcolare la somma totale.

Dipartimento di Informatica 5
Università degli studi di Pisa Callable, Monitor Laura Ricci
THREAD CHE RESTITUISCONO RISULTATI

import java.util.concurrent.Callable;
public class Calculator implements Callable <Integer> {
private int a;
private int b;
public Calculator(int a, int b) {
this.a = a;
this.b = b;
}
public Integer call() throws Exception {
Thread.sleep((long)(Math.random() * 15000));
return a + b;
}
}

Dipartimento di Informatica 6
Università degli studi di Pisa Callable, Monitor Laura Ricci
THREAD CHE RESTITUISCONO RISULTATI
import java.util.ArrayList; import java.util.List; import java.util.concurrent.*;
public class Adder {
public static void main(String[] args) throws ExecutionException,InterruptedException{
// Create thread pool using Executor Framework
ExecutorService executor = Executors.newFixedThreadPool(5);
List<Future<Integer>> list = new ArrayList<Future<Integer>>();
for (int i = 1; i < 11; i=i+2) { // Create new Calculator object
Calculator c = new Calculator(i, i + 1);
list.add(executor.submit(c));}
int s=0;
for (Future<Integer> f : list) {
try { System.out.println(f.get());
s=s+f.get();
} catch (Exception e) {};}
System.out.println("la somma e'"+s);
executor.shutdown(); }}

Dipartimento di Informatica 7
Università degli studi di Pisa Callable, Monitor Laura Ricci
L'INTERFACCIA FUTURE

• sottomettere direttamente l'oggetto


di tipo Callable al pool mediante il
metodo submit

• la sottomissione restituisce un
oggetto di tipo Future

• ogni oggetto Future è associato ad


uno dei task sottomessi al ThreadPool

è possibile applicare diversi metodi

all'oggetto Future

Dipartimento di Informatica 8
Università degli studi di Pisa Callable, Monitor Laura Ricci
L'INTERFACCIA FUTURE
public interface Future <V>
{ V get( ) throws...;
V get (long timeout, TimeUnit) throws...;
void cancel (boolean mayInterrupt);
boolean isCancelled( );
boolean isDone( ); }

• metodo get()

si blocca fino a che il thread non ha prodotto il valore richiesto e
restituisce il valore calcolato
• metodo get (long timeout, TimeUnit)

definisce un tempo massimo di attesa della terminazione del task, dopo
cui viene sollevata una TimeoutException
• è possibile cancellare il task e verificare se la computazione è terminata
oppure è stata cancellata

Dipartimento di Informatica 9
Università degli studi di Pisa Callable, Monitor Laura Ricci
FIGHTING THREDS: CONDIVISIONE DI RISORSE

Dipartimento di Informatica 10
Università degli studi di Pisa Callable, Monitor Laura Ricci
THREAD CHE CONDIVIDONO LA CONSOLE
class Forth implements Runnable {
public void run(){
while(true){
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) { return; }
System.out.print("**********");
System.out.flush();
}
}}

Dipartimento di Informatica 11
Università degli studi di Pisa Callable, Monitor Laura Ricci
THREAD CHE CONDIVIDONO LA CONSOLE
class Back implements Runnable {
public void run(){
while(true){
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) { return; }
System.out.print("\b\b\b\b\b\b\b\b\b\b");
System.out.print("-----------");
System.out.flush();
}
}}

Dipartimento di Informatica 12
Università degli studi di Pisa Callable, Monitor Laura Ricci
THREAD CHE CONDIVIDONO LA CONSOLE
public class BackAndForth {

public static void main(String args[]){


Thread ts= new Thread(new Forth());
ts.start();
Thread bk= new Thread(new Back());
bk.start();
}}

• cosa accade se faccio eseguire il programma?

Dipartimento di Informatica 13
Università degli studi di Pisa Callable, Monitor Laura Ricci
CONDIVIDERE RISORSE TRA THREADS
• un insieme di thread vogliono condividere una risorsa.

più thread accedono concorrentemente allo stesso file, alla stessa parte
di un database o di una struttura di memoria
• l'accesso non controllato a risorse condivise può provocare situazioni di
errore ed inconsistenze.

race conditions
• sezione critica: blocco di codice a cui si effettua l'accesso ad una risorsa
condivisa e che deve essere eseguito da un thread per volta
• necessario implementare classi thread safe

il codice dei metodi della classe può essere utilizzato/condiviso in un
ambiente concorrente senza provocare inconsistenze/comportamenti
inaspettati

Dipartimento di Informatica 14
Università degli studi di Pisa Callable, Monitor Laura Ricci
GENERARE UNA RACE CONDITION
class Cell {
private long value;
public Cell (long v)
{this.value=v;}
public void update(long delta) {
this.value += delta;
}
public long get() {return value;};
}

Dipartimento di Informatica 15
Università degli studi di Pisa Callable, Monitor Laura Ricci
GENERARE UNA RACE CONDITION

class Counter implements Runnable {


public int ticks ;
private Cell cell;
private int delta;
private int maxTicks;
Counter(Cell cell, int delta, int maxTicks) {
this.cell = cell;
this.delta = delta;
this.maxTicks = maxTicks;
}
public void run() {
ticks = 0;
while (ticks < maxTicks) {
cell.update(delta);
++ticks;
}}}
Dipartimento di Informatica 16
Università degli studi di Pisa Callable, Monitor Laura Ricci
GENERARE UNA RACE CONDITION
public class Main {
public static void main(String[] args) {
int MAX_TICKS=1000000;
Cell cell=new Cell(0);
Counter up = new Counter(cell, 1, MAX_TICKS);
Counter down = new Counter(cell, -1, MAX_TICKS);
Thread upWorker = new Thread(up); Risultati restituiti in esecuzioni
diverse
Thread downWorker = new Thread(down);
upWorker.start(); downWorker.start();
try {
upWorker.join(); downWorker.join();}
catch(Exception e) {};
System.out.println("");
System.out.printf("Cell value: %d\n", cell.get());
System.out.flush();}}

Dipartimento di Informatica 17
Università degli studi di Pisa Callable, Monitor Laura Ricci
AGGIORNARE UNA RISORSA CONDIVISA

• una singola istruzione in Cell.update

this.value += delta;

• ma eseguita non in maniera atomica….

• diversi possibili interleavings


• comportamento non deterministico: è quello che vogliamo?
• thread safety
 “nothing bad ever happens”, in qualsiasi interleaving generato
 spesso non banale da ottenere
 problema di messa a punto di programmi concorrenti
• Dipartimento di Informatica 18
Università degli studi di Pisa Callable, Monitor Laura Ricci
JAVA: LOCK IMPLICITE
• due o più thread possono leggere un oggetto condiviso (shared objects, global
data).
• è responsabilità di sincronizzare gli accessi in modo da evitare interleaving
scorretti ed ottenere la thread safeness
• come effettuare la sincronizzazione, in JAVA?
 con lock esplicite (non lo faremo)
 in JAVA, tutti gli oggetti hanno una lock interna (intrinseca, implicita, monitor
lock)
 un synchronized method implementa una critical section con garanzie di
mutua esclusione
 i metodi acquisiscono implicitamente la lock sull’oggetto su cui vengono
chiamati

Dipartimento di Informatica 19
Università degli studi di Pisa Callable, Monitor Laura Ricci
LOCK INTRINSECHE: METODI SINCRONIZZATI

public synchronized void someMethod()


{// Do work}

metodo synchronized : quando viene invocato



tenta di acquisire la lock intrinseca associata all'istanza dell'oggetto su cui
esso è invocato

se l'oggetto è bloccato il thread viene sospeso nella coda associata
all'oggetto fino a che il thread che detiene la lock la rilascia

la lock viene rilasciata al ritorno del metodo

normale

eccezionale, ad esempio con una uncaught exception.

Dipartimento di Informatica 20
Università degli studi di Pisa Callable, Monitor Laura Ricci
LOCK INTRINSECHE: METODI SINCRONIZZATI

class Cell {
private long value;
public Cell (long v)
{this.value=v;}
public synchronized void update(long delta) {
this.value += delta;
}
public long get() {return value;};
}

Dipartimento di Informatica 21
Università degli studi di Pisa Callable, Monitor Laura Ricci
IL MONITOR
• JAVA built-in monitor: classe di oggetti utilizzabili concorrentemente in modo
thread safe

meccanismi di sincronizzazione “ad alto livello”

come viene implementato? ad ogni oggetto (non int o long, solo gli
oggetti), cioè ad ogni istanza di una classe, viene associata

una “intrinsic lock” o lock implicita
• acquisita con metodi o blocchi di codice synchronized. Garantisce la
mutua esclusione nell'accesso all'oggetto
• gestione automatica della coda di attesa, da parte della JVM

una “wait queue” gestita dalla JVM utilizzata per memorizzare i thread che
hanno acquisito la lock, ma sono poi in attesa di una condizione sullo stato
della risorsa

wait

notify/notifyAll
Dipartimento di Informatica 22
Università degli studi di Pisa Callable, Monitor Laura Ricci
UN'OCCHIATA ALL'INTERNO DI UN MONITOR

due code gestite in modo implicito:


Entry Set

threads in attesa di acquisire la lock
Wait Set

threads che hanno eseguito una wait
e sono in attesa di una notifyAll

Dipartimento di Informatica 23
Università degli studi di Pisa Callable, Monitor Laura Ricci
METODI SINCRONIZZATI

• i metodi di un built-in monitor possono essere resi thread safe annotandoli


con la parola chiave synchronized
• coda thread-safe, implementata con monitor
public class MessageQueue {
public MessageQueue(int size)

public synchronized void produce(Object x)


public synchronized Object consume()

l'esecuzione di un metodo synchronized richiede automaticamente
l'acquisizione della la lock intrinseca associata all'oggetto
• l'intero codice del metodo sincronizzato viene serializzato rispetto agli altri
metodi sincronizzati definiti per lo stesso oggetto

solo una thread alla volta può essere eseguire uno dei metodi
synchronized del monitor sulla stessa istanza di una classe

Dipartimento di Informatica 24
Università degli studi di Pisa Callable, Monitor Laura Ricci
LOCK INTRINSECHE: METODI SINCRONIZZATI


i costruttori non devono essere dichiarati synchronized

il compilatore solleva una eccezione

di default, solo il thread che crea l’oggetto accede ad esso mentre l’oggetto
viene creato

non ha senso specificare synchronized nelle interfacce

synchronized non è ereditato da overriding

metodo nella sottoclasse deve essere esplicitamente definito synchronized,
se necessario

la lock è associata ad un'istanza dell’oggetto, non alla classe, metodi su oggetti
che sono istanze diverse della stessa classe possono essere eseguiti in modo
concorrente!

Dipartimento di Informatica 25
Università degli studi di Pisa Callable, Monitor Laura Ricci
WAITING AND COORDINATION MECHANISMS
void wait()
• JAVA fornisce 3 metodi di base per ●
sospende il thread fino a che un altro
coordinare i thread thread invoca una notify()
/notifyAll() sullo stesso oggetto.

invocati su un oggetto, ●
implementa una “attesa passiva” del
verificarsi di una condizione
appartengono alla classe Object ●
rilascia la lock sull'oggetto

occorre acquisire la lock intrinseca prima
void notify()
di invocarli, altrimenti viene sollevate ●
sveglia un singolo thread in attesa su questo
l'eccezione IllegalMonitorException() oggetto

nop se nessun thread è in attesa

eseguiti all'interno di metodi
sincronizzati
void notifyAll()
sveglia tutti i thread in attesa su questo
se non si mette il riferimento ad un

oggetto, che competono per riacquisire


oggetto, il riferimento implicito è this della lock

Dipartimento di Informatica 26
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE CON MONITOR
public class MessageQueue {
int putptr, takeptr, count;
final Object[] items;
public MessageQueue(int size){
items = new Object[size];
count=0;putptr=0;takeptr=0;}
public synchronized void produce(Object x)
{ while (count == items.length)
try {
wait();}
catch(Exception e) {}
// gestione puntatoricoda
items[putptr] = x; putptr++;++count;
if (putptr == items.length) putptr = 0;
System.out.println("Message Produced"+x);
notifyAll();}

Dipartimento di Informatica 27
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE CON MONITOR
public synchronized Object consume() {
while (count == 0)
try {
wait();}
catch(InterruptedException e) {}
// gestione puntatori coda
Object data = items[takeptr]; takeptr=takeptr+1; --count;
if (takeptr == items.length) {takeptr = 0;};
notifyAll();
System.out.println("Message Consumed"+data);
return data;
}}

Dipartimento di Informatica 28
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Consumer extends Thread


{
public void run(){
for(int i=0;i<10;i++){
Object o=queue.consume();
….}

Dipartimento di Informatica 29
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Consumer extends Thread


{
public void run(){
for(int i=0;i<10;i++){
Object o=queue.consume();
….}

Dipartimento di Informatica 30
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Consumer extends Thread


{
public void run(){
for(int i=0;i<10;i++){
Object o=queue.consume();
….}

Dipartimento di Informatica 31
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Consumer extends Thread


{
public void run(){
for(int i=0;i<10;i++){
Object o=queue.consume();
….}

Dipartimento di Informatica 32
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Producer extends Thread


{
public void run(){
for(int i=0;i<10;i++)
{queue.produce("MSG#"+count+Thread.currentThread());
….....

Dipartimento di Informatica 33
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Producer extends Thread


{
public void run(){
for(int i=0;i<10;i++)
{queue.produce("MSG#"+count+Thread.currentThread());
….....

Dipartimento di Informatica 34
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Producer extends Thread


{
public void run(){
for(int i=0;i<10;i++)
{queue.produce("MSG#"+count+Thread.currentThread())
….....

Dipartimento di Informatica 35
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Producer extends Thread


{
public void run(){
for(int i=0;i<10;i++)
{queue.produce("MSG#"+count+Thread.currentThread());
….....

Dipartimento di Informatica 36
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Producer extends Thread


{
public void run(){
for(int i=0;i<10;i++)
{queue.produce("MSG#"+count+Thread.currentThread());
….....

Dipartimento di Informatica 37
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Producer extends Thread


{
public void run(){
for(int i=0;i<10;i++)
{queue.produce("MSG#"+count+Thread.currentThread());
….....

Dipartimento di Informatica 38
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Consumer extends Thread


{
public void run(){
for(int i=0;i<10;i++){
Object o=queue.consume();
….}

Dipartimento di Informatica 39
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Consumer extends Thread


{
public void run(){
for(int i=0;i<10;i++){
Object o=queue.consume();
….}

Dipartimento di Informatica 40
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Consumer extends Thread


{
public void run(){
for(int i=0;i<10;i++){
Object o=queue.consume();
….}

Dipartimento di Informatica 41
Università degli studi di Pisa Callable, Monitor Laura Ricci
PRODUTTORE CONSUMATORE “ILLUSTRATO”

public class Consumer extends Thread


{
public void run(){
for(int i=0;i<10;i++){
Object o=queue.consume();
….}

Dipartimento di Informatica 42
Università degli studi di Pisa Callable, Monitor Laura Ricci
ASSIGNMENT 5: GESTIONE LABORATORIO
Il laboratorio di Informatica del Polo Marzotto è utilizzato da tre tipi di utenti,
studenti, tesisti e professori ed ogni utente deve fare una richiesta al tutor per
accedere al laboratorio. I computers del laboratorio sono numerati da 1 a 20. Le
richieste di accesso sono diverse a seconda del tipo dell'utente:
a) i professori accedono in modo esclusivo a tutto il laboratorio, poichè hanno
necessità di utilizzare tutti i computers per effettuare prove in rete.
b) i tesisti richiedono l'uso esclusivo di un solo computer, identificato
dall'indice i, poichè su quel computer è istallato un particolare software
necessario per lo sviluppo della tesi.
c) gli studenti richiedono l'uso esclusivo di un qualsiasi computer.
I professori hanno priorità su tutti nell'accesso al laboratorio, i tesisti hanno
priorità sugli studenti.
Nessuno però può essere interrotto mentre sta usando un computer (prosegue
nella pagina successiva)

Dipartimento di Informatica 43
Università degli studi di Pisa Callable, Monitor Laura Ricci
ASSIGNMENT 5: GESTIONE LABORATORIO

Scrivere un programma JAVA che simuli il comportamento degli utenti e del


tutor. Il programma riceve in ingresso il numero di studenti, tesisti e professori
che utilizzano il laboratorio ed attiva un thread per ogni utente. Ogni utente
accede k volte al laboratorio, con k generato casualmente. Simulare l'intervallo
di tempo che intercorre tra un accesso ed il successivo e l'intervallo di
permanenza in laboratorio mediante il metodo sleep della classe Thread. Il
tutor deve coordinare gli accessi al laboratorio. Il programma deve terminare
quando tutti gli utenti hanno completato i loro accessi al laboratorio.
Simulare gli utenti con dei thread e incapsulare la logica di gestione del
laboratorio all'interno di un monitor.

Dipartimento di Informatica 44
Università degli studi di Pisa Callable, Monitor Laura Ricci

Potrebbero piacerti anche