Programmazione concorrente con il linguaggio Java

Documenti analoghi
Multithreading in Java. Fondamenti di Sistemi Informativi

Java Virtual Machine. Indipendenza di java dalla macchina ospite. I threads in Java

THREAD IN JAVA. Thread. Un thread (lightweight process) è un singolo flusso sequenziale di controllo all interno di un processo

Programmazione concorrente in Java

Java Virtual Machine

Gestione dei thread in Java LSO 2008

THREAD. Programmazione in rete e laboratorio. Come si crea un thread

Programmazione concorrente con il linguaggio Java Threads

Java threads (2) Programmazione Concorrente

T 1. Per un processo con più thread di controllo, lo stato di avanzamento della computazione di ogni thread è dato da:

Con il pulsante Start si introducono palline che rimbalzano in un area di disegno fino a che non è terminato il loro ciclo di vita (1000 movimenti).

I thread di uno stesso processo condividono dati e codice del processo, ma lo stack di esecuzione ed il program counter sono privati.

Decima Esercitazione. Accesso a risorse condivise tramite Monitor Java

Definizione di thread Proprietà dei thread in Java Gestione delle priorità nei programmi multithreaded Gruppi di thread Accesso a variabili condivise

Processi e Thread. Walter Cazzola Dipartimento di Informatica e Comunicazione Università à degli Studi di Milano.

Esercitazioni 7 e 8. Bounded Buffer con sincronizzazione Java (1)

Linguaggi Corso M-Z - Laurea in Ingegneria Informatica A.A lezione 14 - Thread in Java

Terza Esercitazione. Unix - Esercizio 1. Unix System Call Exec Java Introduzione Thread

Esercitazione 15. Il problema dello Sleeping Barber

Laboratorio di Sistemi Thread Java

Esercizio monitor. Sistemi Operativi T 1

Ottava Esercitazione. introduzione ai thread java mutua esclusione

Multi-threading. I programmi Java possono eseguire thread multipli in modalità di concorrenza logica. Come funziona il multi-threading?

Esercizi sugli Oggetti Monitor

SAPIENZA Università di Roma Facoltà di Ingegneria dell Informazione, Informatica e Statistica

Programmazione Concorrente in Java

GESTIONE DEI PROCESSI

Laboratorio Reti di Calcolatori Laurea Triennale in Comunicazione Digitale. Anno Accademico 2012/2013

19. Introduzione al multi-threading

Programmazione multi threaded in Python. Linguaggi dinamici A.A. 2010/2011 1

Thread e Task. L20_MultiThread 2

Esercizi sul Monitor in Java

Multithreading in Java

Un esercizio d esame. Flavio De Paoli

Esercitazioni Ingegneria del So2ware 8 Threads. Giordano Tamburrelli tamburrelli@elet.polimi.it h@p://giordano.webfacdonal.com

Lezione 15 Programmazione multithreaded

Programmazione Orientata agli Oggetti in Linguaggio Java

Telematica II 17. Esercitazione/Laboratorio 6

Programmazione. Cognome... Nome... Matricola... Prova scritta del 11 luglio 2014

Laboratorio di Programmazione Lezione 2. Cristian Del Fabbro

Modelli di interazione tra processi

Sincronizzazione con Java

Lab 1: Java Multithreading

Lezione n.2b. Threads: Callable & Future. 6/10/2008 Vincenzo Gervasi

progam ponteasensounicoalaternato ; type dir = ( nord, sud );

THREAD IN JAVA. Come si può realizzare il concetto di Thread in Java?

Esercizio 6 Realizzare una classe astratta per le Figure piane e due sottoclassi, la sottoclasse Quadrato e la sottoclasse Rettangolo.

Corso di Programmazione Concorrente. Java Thread. Valter Crescenzi

Programmazione concorrente e threads

Programmazione concorrente in Java. Dr. Paolo Casoto, Ph.D

Thread in Java CAPITOLO Richiami di gestione di processi

Un programma concorrente è un programma nel quale diverse computazioni possono essere eseguite allo stesso tempo Alcuni sistemi sono implicitamente

Ingegneria del Software

Modelli di interazione tra processi

Programmazione. Cognome... Nome... Matricola... Prova scritta del 22 settembre Negli esercizi proposti si utilizzano le seguenti classi:

Le risorse. Alcune definizioni

Synchronized (ancora)

Programmazione Java Struttura di una classe, Costruttore, Riferimento this

Programmazione Java Threads

Esercizi della lezione 5 di Java

Gruppi di Thread. Java threads (3) Gruppi di thread e Timer. Operating Systems. Operating Systems. Java threads 3. Java threads 3

Informatica 3 secondo recupero 13 Settembre 2002

Variabili e Metodi di classe Interfacce e Package Gestione di File in Java

Supporto al Sistema Operativo

public BankAccount() { balance = 0; } public BankAccount(double initialbalance) { balance = initialbalance; }

Lab 4: Locks, Condition Variables in Java

sayhello public private protected return public class Greeter { public String sayhello() { String message = Hello, World! ; return message; } }

SEMAFORI SEMAFORI. Sul semaforo sono ammesse solo due operazioni (primitive)

SISTEMI OPERATIVI. Sincronizzazione in Java (Monitor e variabili condizione in Java)

Soluzioni ai problemi di Mutua Esclusione Primitive di sincronizzazione. Soluzioni ai problemi di Mutua EsclusionePrimitive di sincronizzazione

Corso sul linguaggio Java

UNIVERSITÀ DEGLI STUDI DI BERGAMO

24 - Possibili approfondimenti

Esercizi di utilizzo del semaforo semplice di competizione per l'uso di una risorsa comune

La concorrenza in Java package java.util.concurrent Antonio Furone

7 - Programmazione procedurale: Dichiarazione e chiamata di metodi ausiliari

Algebra di Boole: Concetti di base. E un algebra basata su tre operazioni logiche

public double getlato() restituisce la lunghezza del lato del quadrato che esegue il metodo.

Programmazione di Reti Corso B. 23 Febbraio 2016 Lezione 1(b)

Programmazione I. 11 gennaio Considerate la seguente gerarchia di classi (rappresentata mediante un diagramma UML): +f(double x):

Le basi del linguaggio Java

Compute engine generici in RMI

Sistemi Operativi. Lez. 13: primitive per la concorrenza monitor e messaggi

Chat. Si ha un server in ascolto sulla porta Quando un client richiede la connessione, il server risponde con: Connessione accettata.

Il linguaggio Java. La superclasse universale Object

Uso di metodi statici. Walter Didimo

ESERCIZIO SincrAmbGlob-1

Esempio: L EURO-CONVERTITORE (1) Scopo

Programmazione Orientata agli Oggetti in Linguaggio Java

SavingsAccount. BankAccount

Eccezioni Precisazioni e approfondimenti

RETI DI CALCOLATORI Linguaggio Java: Eccezioni

ACSO Programmazione di Sistema e Concorrente

Corso di Laurea in Matematica Corso di Informatica Prova d Esame del 02/02/2010

Gestione delle Eccezioni

18 - Classi parzialmente definite: Classi Astratte e Interfacce

Tipi primitivi. Ad esempio, il codice seguente dichiara una variabile di tipo intero, le assegna il valore 5 e stampa a schermo il suo contenuto:

Laboratorio di Programmazione di Rete Corso A

PROCESSI ESEMPIO THREAD. RETI DI CALCOLATORI Linguaggio Java: i Thread CORSO DI. Università degli Studi di Modena e Reggio Emilia

Sistemi operativi - Concetti ed esempi -Settima edizione

Transcript:

Programmazione concorrente con il linguaggio Java Thread, Mutua Esclusione e Sincronizzazione Alcuni aspetti architetturali e di prestazioni

Concetto di thread Un thread è un flusso di esecuzione indipendente L esecuzione di un programma Java (processo) può essere costituita da uno o più thread Il thread principale è quello che esegue il metodo main Un programma Java termina quando tutti i thread che lo compongono sono terminati (in prima approssimazione) 2

Creazione di un thread Primo metodo: Sottoclasse Thread Dichiarare una classe (es. HelloThread) come sottoclasse di Thread (package: java.lang) Sovrascrivere il metodo run() della classe Thread Creare un oggetto della classe HelloThread ed invocare il metodo start() per attivarlo public class HelloThread extends Thread { public void run() { System.out.println("Hello from thread!"); public static void main(string args[]) { (new HelloThread()).start(); 3

Creazione di un thread Secondo metodo: oggetto Runnable Definire una classe (es. HelloRun) che implementa l interfaccia Runnable. N.B. Runnable ha il metodo run(). Creare un oggetto della classe HelloRun Creare un oggetto di classe Thread passando un oggetto HelloRun al costruttore Thread(). Attivare l oggetto Thread con il metodo start() public class HelloRun implements Runnable { public void run() { System.out.println("Hello from a thread!"); public static void main(string args[]) { (new Thread(new HelloRun())).start(); 4

Creazione di Thread (Thread) class SimpleThread extends Thread { public SimpleThread(String str) { super(str); public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + getname()); try { sleep((long)(math.random() * 1000)); catch (InterruptedException e) { System.out.println("FINITO! " + getname()); public class TwoThreadsDemo { public static void main (String[] args) { new SimpleThread( Pippo").start(); new SimpleThread("Pluto").start(); OUTPUT 0 Pippo 0 Pluto 1 Pluto 2 Pluto 3 Pluto 1 Pippo 4 Pluto 2 Pippo 3 Pippo 4 Pippo 5 Pippo 5 Pluto 6 Pluto 7 Pluto 6 Pippo 8 Pluto 7 Pippo 9 Pluto FINITO! Pluto 8 Pippo 9 Pippo FINITO! Pippo 5

Creazione di thread (Runnable) class SimpleThread implements Runnable { private Thread thr; public SimpleThread(String str) { thr = new Thread(this, str); thr.start(); public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + thr.getname()); try { Thread.sleep((long)(Math.random() * 1000)); catch (InterruptedException e) { System.out.println("FINITO! " + thr.getname()); public class TwoThreadsDemo { public static void main (String[] args) { new SimpleThread("Pippo"); new SimpleThread("Pluto"); 6

Stato di un thread (prima approssimazione) Quando si scrive un programma multi-threaded bisogna pensare che ciascun thread ha il proprio processore (virtuale) Un thread può trovarsi in un particolare stato Esecuzione: il thread sta utilizzando il processore Bloccato: l esecuzione del thread è sospesa in attesa di un evento NUOVO start new ESECUZIONE eccezione notify/notifyall evento esterno BLOCCATO Il metodo run termina TERMINATO sleep wait, synchronized I/O 7

Variabili condivise I thread appartenenti ad uno stesso programma hanno variabili private e variabili comuni Con riferimento all esempio Variabili private: p, b, t; Variabili condivise: s, oggetto riferito da b (possibile) class SimpleThread extends Thread { private int p; private static int s; private BankAccount b; public SimpleThread(BankAccount x) { b = x; public void run() { int t; b.withdraw(50); //... 8

Mutua esclusione L accesso di thread concorrenti a strutture dati condivise deve essere coordinato Se due thread concorrenti eseguono contemporaneamente l operazione withdraw si possono avere delle inconsistenze boolean withdraw(int amt) { if (balance amt >= 0) { balance -= amt; return true; return false; Invariante: balance >= 0 balance = 80 amt = 50 thread 1 thread 2 balance balance amt >= 0 80 balance amt >= 0 80 balance -= amt 30 balance -= amt -20 Ogni thread deve eseguire l operazione withdraw per intero (atomicamente) 9

Sezioni critiche Sezione critica: - Sequenza di istruzioni che deve essere eseguita in modo mutuamente esclusivo con altre sezioni critiche Classe di sezioni critiche: - Insieme di sezioni critiche le cui esecuzioni devono essere mutuamente esclusive Java identifica la sezione critica per mezzo della parola chiave synchronized - Metodo sincronizzato - Blocco sincronizzato boolean synchronized withdraw(int amt) { if (balance amt >= 0) { balance -= amt; return true; return false; 10

La classe completa class BankAccount { private double balance; public synchronized deposit(double amount) { //... public synchronized withdraw(double amount) { //... 11

Metodi sincronizzati synchronized Method_Name (args) Method_Block Java associa un lock ad ogni oggetto (sincronizzazione sull oggetto) Esecuzione di un metodo sincronizzato da parte di un thread Il thread acquisisce il lock sull oggetto (entra in sezione critica). Se il lock non è disponibile, il thread attende finchè non viene rilasciato; Il thread esegue il corpo del metodo Method_Block Il thread rilascia il lock (esce dalla sezione critica) se l'esecuzione del corpo è terminata da un eccezione, la sezione critica viene rilasciata; Se più thread sono in attesa del rilascio, essi si contenderanno il lock quando questo viene rilasciato (gestione FIFO) Mentre un thread detiene un lock, nessun altro thread può acquisirlo 12

Blocchi sincronizzati synchronized ( Expression ) Block Expression deve produrre un valore V di tipo riferimento non-null. - Se l espressione termina abruptly, l istruzione termina abruptly. Il thread acquisisce la mutua esclusione su (l oggetto riferito da) V Esegue il blocco Block ed infine rilascia la mutua esclusione V. - Se il blocco termina abruptly, il lock viene rilasciato e l istruzione termina abruptly. 13

Blocchi e metodi sincronizzati synchronized void m(args) { /* sezione critica */ è equivalente a void m(args) { synchronized (this) { /* sezione critica */ 14

Lock rientranti La mutua esclusione in Java è rientrante: un thread può riacquisire un lock già acquisito evitando il blocco critico (deadlock) public class Rientrante { public synchronized void a() { b(); System.out.println("Sono in a()"); public synchronized void b() { System.out.println("Sono in b()"); public static void main(string[] args) { Rientrante r = new Rientrante(); r.a(); // output Sono in b() Sono in a() 15

Il blocco critico Si ha una situazione di blocco critco quando i thread sono bloccati in un attesa circolare Esempio: Il thread T1 è bloccato in attesa del thread T2 che è bloccato in attesa di T3 che è bloccato in attesa del thread T1. T2 T1 T3 Tn 16

Sincronizzazione sulla classe Se una classe contiene variabili statiche, la sincronizzazione sull oggetto non è sufficiente Metodi su oggetti diversi possono accedere alle stesse variabili statiche È quindi necessaria una sincronizzazione sulla classe synchronized (getclass()) block 17

Esempio: metodo yield 1. public class MyThread extends Thread { 2. private int tick = 1, num; 3. private final static int NUMTH=2; 4. public MyThread(int num){this.num = num; 5. public void run() { 6. while(tick < 400000){ 7. tick++; 8. if((tick % 50000) == 0){ 9. System.out.println("Thread "+num); 10. yield(); 11. 12. 13. 14.public static void main(string[] args) { 15. MyThread[] runners=new MyThread[NUMTH]; 16. for (int i=0;i<numth;i++){ 17. runners[i] = new MyThread(i); 18. runners[i].setpriority(norm_priority+i); 19. 20. for (int i=0; i<numth;i++) 21. runners[i].start(); 22. 18 Esecuzione: Quando il thread a più alta priorità prende la CPU non la rilascia più Commento linea 18: Thread hanno pari priorità. Ogni 50000 tick, il thread rilascia la CPU a beneficio degli altri. Commento linea 10 e 18: Thread hanno pari priorità. Se il sistema non è time-sliced, quando un thread prende la CPU non la rilascia più.

Metodi della classe Thread run: - contiene il corpo del thread start: - t.start() esegue il thread t getname / getpriority : - restituisce il nome o la priorità del thread setname / setpriority: - modifica del nome o della priorità del thread sleep: - sospende l esecuzione del thread per m millisecondi (valore di m passato come argomento) yield: - sospende l esecuzione del thread corrente consentendo l esecuzione di altri thread pronti e a uguale priorità join: - t.join() attende la terminazione del thread t 19

Sincronizzazione fra threads

Problema della sincronizzazione In alcuni problemi la mutua esclusione non basa ma bisogna anche garantire la sincronizzazione fra i threads. Esempio: Problema del Produttore-Consumatore. - Requisiti - 1) Ciascun valore prodotto deve essere consumato; - 2) nessun valore prodotto può essere consumato due o più volte buffer P operazione buffer.put(v) valore operazione C val = buffer.get() 21

Produttore-Consumatore P operazione buffer.put(a) buffer disponibile false valore attesa C val = buffer.get() P attesa buffer.put(b) Buffer disponibile true valore a operazione C v = buffer.get() 22

Soluzione: Produttore 1. public class Produttore extends Thread { 2. private Buffer buffer; 3. private int numero; 4. public Produttore(Buffer b, int numero) { 5. buffer = b; 6. this.numero = numero; 7. 8. public void run() { 9. for (int i = 0; i < 10; i++) { 10. buffer.put(i); 11. System.out.println("Produttore #"+this.numero+"put:"+i); 12. 13. 14. 23

Soluzione: Consumatore 1. public class Consumatore extends Thread { 2. private Buffer buffer; 3. private int number; 4. public Consumatore(Buffer b, int numero) { 5. buffer = b; 6. this.number = numero; 7. 8. public void run() { 9. int valore = 0; 10. for (int i = 0; i < 10; i++) { 11. valore = buffer.get(); 12. System.out.println("Consumatore #"+this.number+"get:"+ valore); 13. 14. 15. 24

Soluzione (errata): il buffer 1. public class Buffer { 2. private int valore; 3. private boolean disponibile = false; 4. public int get() { 5. while (disponibile == false); 6. disponibile = false; 7. return valore; 8. 9. public void put(int value) { 10. while (disponibile == true); 11. valore = value; 12. disponibile = true; 13. 14. 25

Soluzione: Esecuzione Produttore #1 put: 0 Produttore #1 put: 1 Consumatore #1 got: 1 Consumatore #1 got: 1 Produttore #1 put: 2 Consumatore #1 got: 3 Produttore #1 put: 3 Produttore #1 put: 4 Consumatore #1 got: 4 Consumatore #1 got: 4 Produttore #1 put: 5 Consumatore #1 got: 6 Produttore #1 put: 6 Produttore #1 put: 7 Se P è più veloce di C, P può produrre il valore successivo prima che C abbia consumato quello corrente Se C è più veloce di P, C può consumare più volte il valore corrente prima che P abbia prodotto quello successivo Addirittura può sembrare che C consumi un valore prima che P lo abbia prodotto 26

Sincronizzazione: uso del Monitor Il monitor permette di aggiungere alla definizione di tipo di dati astratto una specifica della sincronizzazione fra i threads per mezzo dell invocazione dei seguenti metodi: - wait(): tale metodo rilascia il lock (mutua esclusione) sull'oggetto e sospende il thread che lo invoca in attesa di una notifica. - notifyall(): tale metodo risveglia tutti i thread sospesi sull'oggetto in attesa di notifica. I thread risvegliati competono per acquisire il lock (mutua esclusione) sull'oggetto. - notify(): tale metodo risveglia un thread scelto casualmente tra quelli sospesi sull'oggetto in attesa di notifica. Il thread risvegliato compete per acquisire il lock (mutua esclusione) sull'oggetto. I metodi wait(), notify() e notifyall() devono essere invocati dall'interno di un metodo o blocco sincronizzato 27

Soluzione (corretta): il buffer public class Buffer { private int valore; private boolean disponibile = false; public syncronized int get() { while (disponibile == false) { try { wait(); catch(interruptedexception e){ disponibile = false; notifyall(); return valore; public synchronized void put(int value) { while (disponibile == true) { try { wait(); catch(interruptedexception e){ valore = value; disponibile = true; notifyall(); 28

Il gestore di risorse equivalenti Un gestore gestisce N risorse equivalenti (buffer di memoria, stampanti, ) Ciascuna risorsa è identificata da un numero intero compreso tra 0 e N-1 Il gestore offre due operazioni: richiesta e rilascio L operazione int richiesta alloca una risorsa dispoonibile al thread richiedente ritornandone il nome; se nessuna risorsa è al momento disponibile, l esecuzione dell operazione richiesta si sospende fino a quando una una risorsa diventerà disponibile L operazione void rilascio(int i) rende disponibile la risorsa i allocata al thread in esecuzione e notifica la disponibilità din una nuova risorsa. 29

Gestore di un pool di risorse equivalenti risorse 0 N: numero totale di risorse disponibili: risorse disponibili (initial N) risorse risorse[i] = true => la risorsa i è disponibile risorse[i] = false => la risorsa i è occupata risorse[i] initial true N-1 N int richiesta() rilascio(int i) disponibili 30