51
Dipartimento di Informatica Università degli Studi di Pisa RMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento di Informatica Lezione n.11 LPR – Informatica Applicata Approfondimenti su RMI e Threads 22/05/2012 Laura Ricci

Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 1

Università degli Studi di Pisa Dipartimento di Informatica

Lezione n.11LPR – Informatica Applicata

Approfondimenti suRMI e Threads

22/05/2012Laura Ricci

Page 2: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 2

RMI: IMPLEMENTAZIONE

• Analizziamo le caratteristiche di un servizio remoto– non vogliamo analizzare dettagliatamente l'implementazione– studiamo il comportamento tramite un insieme di esempi

• Vogliamo capire:

– poiché esiste un solo oggetto remoto, i metodi di quell'oggetto possono essere invocati in modo concorrente da client diversi o da thread diversi dello stesso client?

– In caso affermativo, viene creato un thread per ogni richiesta? Per ogni client?

– cosa accade se non sincronizzo opportunamente gli accessi sull'oggetto remoto?

Page 3: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 3

RMI: INVOCAZIONE CONCORRENTE DI METODI

Per verificare se i metodi dell'oggetto remoto sono invocati in modo concorrente, • definiamo un oggetto remoto che esporta due metodi• ogni metodo non fa altro che stampare per un certo numero di volte che

è in esecuzione• attiviamo due client: uno invoca il primo metodo, uno il secondo

– si ottiene un interleaving delle stampe ! public interface threads extends java.rmi.Remote { public void MethodOne() throws java.rmi.RemoteException;

public void MethodTwo() throws java.rmi.RemoteException;

}

Page 4: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 4

RMI: INVOCAZIONE CONCORRENTE DI METODI

import java.rmi.*;public class threadsimpl implements threads { public threadsimpl() throws RemoteException {super();} public void MethodOne() throws RemoteException { long TimeOne = System.currentTimeMillis(); for(int index=0;index<25;index++) { System.out.println("Method ONE executing"); // Inserito un ritardo di circa mezzo secondo do{ }while ((TimeOne+500)>System.currentTimeMillis()); TimeOne = System.currentTimeMillis(); } }

Page 5: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 5

RMI: INVOCAZIONE CONCORRENTE DI METODI

public void MethodTwo() throws RemoteException { long TimeTwo = System.currentTimeMillis(); for(int index=0;index<25;index++) { System.out.println("Method TWO executing"); // Inserito un ritardo di circa mezzo secondo do{ }while ((TimeTwo+500)>System.currentTimeMillis()); TimeTwo = System.currentTimeMillis(); } } }

Page 6: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 6

RMI: INVOCAZIONE CONCORRENTE DI METODI

import …...public class threadserver { public threadserver() { try {LocateRegistry.createRegistry(args[0]); Registry r=LocateRegistry.getRegistry(args[0]); System.out.println("Registro Reperito"); threadsimpl c = new threadsimpl(); threads stub =(threads) UnicastRemoteObject.exportObject(c, 0); r.rebind("Threads", stub); } catch (Exception e) { System.out.println("Server Error: " + e); } } public static void main(String args[]) { new threadserver(); }}

Page 7: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 7

RMI: INVOCAZIONE CONCORRENTE DI METODI

public class threadsclient { public static void main(String[] args) { try { Registry r= LocateRegistry.getRegistry(args[0]); threads c = (threads) r.lookup("Threads"); if (args[1].equals("one")) c.MethodOne(); else if (args[1].equals("two")) c.MethodTwo(); else System.out.println("Error: correct usage - treadsclient port {one|two}");

} catch (Exception e){ }}}

Page 8: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 8

RMI: INVOCAZIONE CONCORRENTE DI METODI

Una possibile traccia di esecuzione

Page 9: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 9

RMI: INVOCAZIONE CONCORRENTE DI METODI

Dalla documentazione ufficiale“A method dispatched by the RMI runtime to a remote object implementation (a server) may or may not execute in a separate thread. Calls originating from different clients Virtual Machines will execute in different threads. From the same client machine it is not guaranteed that each method will run in a separate thread”

• Invocazioni di metodi remoti provenienti da client diversi sono eseguite da diversi thread– consente di non bloccare un client in attesa della terminazione

dell'esecuzione di un metodo invocato da un altro client – ottimizza la performance del servizio remoto

• Invocazioni concorrenti provenienti dallo stesso client possono essere eseguite dallo stesso thread o da thread diversi

Page 10: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 10

RMI: INVOCAZIONE CONCORRENTE DI METODI

• Supporto RMI utilizza multithreading

• Può comportare comportamenti non thread-safe

• Due client diversi possono aggiornare concorrentemente una struttura dati condivisa, producendo risultati errati– perdita di aggiornamenti

• occorre assicurare il corretto accesso alla struttura dati condivisa

Page 11: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 11

CONDIVISIONE OGGETTO REMOTO

import java.rmi.Remote;import java.rmi.RemoteException;

public interface Fib extends Remote {

int getNextFib() throws RemoteException;

}

Page 12: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 12

CONDIVISIONE OGGETTO REMOTO

import java.rmi.*; import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry; import java.rmi.server.*;

public class FibServer implements Fib { private int F1; private int F2; public FibServer() throws RemoteException { F1 = 1; F2 = 2; } public int getNextFib() throws RemoteException { int temp = F1; F1 = F2; F2 = temp + F2; return temp;}

Page 13: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 13

CONDIVISIONE OGGETTO REMOTO

public static void main (String args[]) { try{LocateRegistry.createRegistry(args[0]); System.out.println("Registro Creato"); Registry r=LocateRegistry.getRegistry(args[0]); System.out.println("Registro Reperito"); FibServer statsServer = new FibServer(); Fib stub =(Fib) UnicastRemoteObject.exportObject(statsServer,0); r.rebind("FIB-SERVER", stub); } catch (RemoteException e) { System.out.println("Communication error " + e.toString());}}}

Page 14: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 14

CONDIVISIONE OGGETTO REMOTO

import java.rmi.*;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry; import java.lang.*;public class FibClient {public static void main (String args[]) { Fib serverObject; Remote RemoteObject; try { Registry r= LocateRegistry.getRegistry(args[0]); RemoteObject = r.lookup("FIB-SERVER"); serverObject = (Fib)RemoteObject; for (int i = 0; i < 10; i++ System.out.println(serverObject.getNextFib()+"\n");} } catch (Exception e) { e.printStackTrace();}}}

Page 15: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 15

CONDIVISIONE OGGETTO REMOTO

Client1: risultati restituiti1, 2, 3, 5, 8, 13, 21, 34, 55, 89

Client2: risultati restituiti144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946

L'esecuzione di Client2 è iniziata dopo che Client1 è terminato, ma il riferimento all'oggetto remoto è rimasto lo stesso.

Page 16: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 16

CONDIVISIONE OGGETTO REMOTO

• Il server genera una unca sequenza di numeri di Fibonacci, che viene 'condivisa' dai due client che accedono concorrentemente

• E' stato creato un unico oggetto remoto

• Il supporto può attivare più threads, uno per ogni client, ma ognuno di questi fa riferimento allo stesso oggetto remoto

• Comportamento non corretto per la semantica del servizio

• In generale problemi di sincronizzazione a strutture dati comuni

Page 17: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 17

POLLING SERVER: ESERCIZIO 2/5/2012

import java.net.*; import java.io.*; import java.util.*;public class SocketPolling{ public static void main(String[] args) throws Exception { LinkedList ll= new LinkedList(); SocketConsumer sc = new SocketConsumer(ll); ServerSocket ss = new ServerSocket(args[0]); sc.start(); while(true) { Socket socket = ss.accept(); System.out.println("connessione accettata"); synchronized(ll) { ll.add(new SocketBucket(socket)); ll.notify();}}}}

Page 18: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 18

POLLING SERVER

import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.Socket;public class SocketBucket { public Socket socket; public ObjectOutputStream out; public ObjectInputStream in; public SocketBucket(Socket socket) throws IOException { this.socket = socket; out = new ObjectOutputStream(socket.getOutputStream()); in = new ObjectInputStream(socket.getInputStream()); socket.setSoTimeout(1); } }

Page 19: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 19

POLLING SERVER

import......;

public class SocketConsumer extends Thread {

Vector sockets = new Vector(); LinkedList newSockets; public SocketConsumer(LinkedList newSockets) { super("ServerThread"); this.newSockets=newSockets; }

Page 20: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 20

POLLING SERVER

public void run() { long dreamTime = 10; boolean foundSomething=false; System.out.println("thread attivato"); while(true) { if (this.newSockets!=null) synchronized(newSockets) { sockets.addAll(newSockets); newSockets.clear(); }

Page 21: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 21

POLLING SERVER

if (sockets!=null) { Iterator it = sockets.iterator(); while(it.hasNext()) { SocketBucket bucket = (SocketBucket)it.next(); try { bucket.in.readObject(); foundSomething = true; bucket.out.writeObject(new String("Client servito")); System.out.println("ClientServito"); bucket.out.flush(); bucket.out.reset(); } catch(Exception ex) {} }}

Page 22: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 22

POLLING SERVER

if (foundSomething) { dreamTime = 6; } else { if (dreamTime < 1000) dreamTime *= 1.5; else dreamTime = 1000; synchronized(newSockets) { try{ newSockets.wait(dreamTime); } catch(Exception e){} }}}}}

Page 23: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 23

IL PROBLEMA DEI 5 FILOSOFI

cinque filosofi siedono ad una tavola rotonda con un piatto di spaghetti davanti, una forchetta (o bacchette cinesi, a seconda della versione)a destra e una forchetta a sinistra

la vita di un filosofo alterna periodi in cui mangia a quelli in cui pensa

ciascun filosofo ha bisogno di due forchette per mangiare, ma che le forchette vengano prese una per volta. Dopo essere riuscito a prendere due forchette il filosofo mangia per un pò, poi lascia le forchette e ricomincia a pensare

Page 24: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 24

IL PROBLEMA DEI 5 FILOSOFI

Problema proposto da E.Dijkstra nel '65: sviluppo di un algoritmo che impedisca lo stallo (deadlock) o la morte d'inedia (starvation).

Il deadlock può verificarsi se ciascuno dei filosofi tiene in mano una forchetta senza mai riuscire a prendere l'altra. Il filosofo F1 aspetta di prendere la forchetta che ha in mano il filosofo F2, che aspetta la forchetta che ha in mano il filosofo F3, e così via in un circolo vizioso.

Page 25: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 25

IL PROBLEMA DEI 5 FILOSOFI

problema proposto da E.Dijkstra nel '65 come problema di sincronizzazione tra più attività concorrenti

Starvation si verifica quando un processo non riesce mai ad acquisire le risorse di cui ha bisogno

la situazione di starvation può verificarsi indipendentemente dal deadlock se uno dei filosofi non riesce mai a prendere entrambe le forchette.

Page 26: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 26

IL PROBLEMA DEI 5 FILOSOFI

public class Philosopher implements Runnable { private final Object left; private final Object right; public Philosopher(Object left, Object right) {this.left = left; this.right = right;}

private void ponder() throws InterruptedException { Thread.sleep(((int) Math.random() * 10) + 10);} public void run() { try { while (true) { synchronized (left) { synchronized (right) { ponder(); // eating } } } } catch (InterruptedException e) { return; } } }

Page 27: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 27

IL PROBLEMA DEI 5 FILOSOFI

import java.util.Collection;public class Dinner { public static void main(String[] args) throws Exception { final Philosopher[] philosophers = new Philosopher[5]; Object[] chopsticks = new Object[philosophers.length]; for (int i = 0; i < chopsticks.length; i++) { chopsticks[i] = new Object(); } for (int i = 0; i < philosophers.length; i++) { Object left = chopsticks[i]; Object right =chopsticks[(i + 1) % chopsticks.length]; philosophers[i] = new Philosopher(left, right); Thread t = new Thread(philosophers[i], "Phil "+(i + 1)); t.start();}}}

Page 28: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 28

IL PROBLEMA DI 5 FILOSOFI

• Si può facilmente verificare che il programma può andare in deadlock

• Tutti i filosofi raccolgono la bacchetta di sinistra, poi tentano di raccogliere quella di destra, che però è già stata raccolta dal filosofo vicino

• Bacchette modellate come oggetti generici – interessa solo utilizzare la lock associata all'oggetto bacchetta– synchronized (left/right) applicata all' oggetto left/right

• acquisisce la lock sull'oggetto• rilascia la lock su quell'oggetto solo quando il blocco di codice che

segue (quello tra parentesi dopo la parola chiave synchronized termina)

• tutti i filosofi acquisiscono la lock sull'oggetto left, poi tentano di acquisire la lock sull'oggetto right

Page 29: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 29

ESERCIZIO

• Scrivere una versione dei 5 filosofi in cui non si possa verificare il

deadlock

Page 30: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 30

THREAD MONITORING

• per verificare automaticamente la presenza del deadlock, utilizzare l'interfaccia ThreadMXBean che consente di monitorare la esecuzione dei thread– contention monitoring: informazioni circa il tempo trascorso da un

thread in stato di bloccato e in attesa di una notifica– thread CPU time: utilizzo della CPU da parte di un thread in user mode– synchronization information e deadlock detection

• individuazione della presenza di deadlock• locks possedute dal thread e lock su cui il thread è in attesa

• implementazione della interfaccia: MXBean– per ottenere un oggetto di tipo MXBean MXBeanManagementFactory.getThreadMXBean()

• diversi metodi utilizzano l'identificatore di un thread o un vettore contenente un insieme di identificatori – identificatori di thread di tipo long

Page 31: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 31

IL PROBLEMA DEI 5 FILOSOFI

import java.lang.management.*; import java.util.*;public class DeadlockChecker { private final static ThreadMXBean tmb = ManagementFactory.getThreadMXBean();public Collection<ThreadInfo> check() { Map<Long, ThreadInfo> map = new HashMap<Long,ThreadInfo>(); storeDeadlockInfo(map, tmb.findMonitorDeadlockedThreads()); storeDeadlockInfo(map, tmb.findDeadlockedThreads()); return map.values(); }private void storeDeadlockInfo(Map<Long, ThreadInfo> result, long[] ids) { if (ids != null && ids.length > 0) { for (long id:ids) {result.put(id,tmb.getThreadInfo(id));}}}

Page 32: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 32

IL PROBLEMA DEI 5 FILOSOFI

public class Dinner {// tutto il codice precedente della classe Dinner…......DeadlockChecker checker = new DeadlockChecker(); while (true) { Collection<ThreadInfo> threads = checker.check(); if (!threads.isEmpty()) { System.out.println("Found deadlock:"); for (ThreadInfo thread : threads) System.out.println("\t" +thread.getThreadName() System.exit(1); } } Thread.sleep(1000); }

Page 33: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 33

IL PROBLEMA DEI 5 FILOSOFI

OUTPUT PRODOTTO DALLA ESECUZIONE DEL PROGRAMMA:

Found deadlock:Phil 1Phil 2Phil 3Phil 4Phil 5

Page 34: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 34

THREAD/THREADPOOL PERFORMANCE

• Abbiamo più volte detto che l'utilizzo dei threadpool introduce il riuso dello stesso thread per più task e consente quindi di ridurre l'overhead introdotto dalla attivazione dei thread

• Il prossimo programma mostra:– come controllare il numero dei threads attivi contemporaneamente in

un programma

– confronta le prestazioni nel caso di un thread per task /riuso dei therads

• Utilizza oggetti di tipo Semaphore

Page 35: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 35

THREAD/THREADPOOL PERFORMANCE

Semaphore: implementa un semaforo a contatore.• semaforo che include un insieme di c tokens• al momento della inizializzazione del semaforo, il valore del semaforo viene

posto a c (tutti i token disponibili)• Operazioni:

– acquire( ): blocca il thread se non è disponibile un token, altrimenti diminuisce di 1 il numero di tokens

– acquire (int count): blocca il thread se non sono disponibili count token, altrimenti diminuisce di count il numero di token

– release( ): aumenta di uno il numero di token, sblocca eventuali thread in attesa

– release (int count): aumenta di count il numero di token, sblocca eventuali threda in attesa

Page 36: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 36

THREAD/THREADPOOL PERFORMANCE

import java.util.concurrent.*;

public class ThreadConstructTest { private static final int NUMBER_OF_THREADS = 100 *1000; private Semaphore semaphore = new Semaphore(10); private final Runnable job = new Runnable() { public void run() { // wait for (int i=0; i<1000; i++) { } semaphore.release(); } };

Page 37: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 37

THREAD/THREADPOOL PERFORMANCE

public void noThreadPool() throws InterruptedException { for (int i = 0; i < NUMBER_OF_THREADS; i++) { semaphore.acquire(); new Thread(job).start(); } // wait for all jobs to finish semaphore.acquire(10); semaphore.release(10); }

Page 38: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 38

THREAD/THREADPOOL PERFORMANCE

public void fixedThreadPool() throws InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(12); for (int i = 0; i < NUMBER_OF_THREADS; i++) { semaphore.acquire(); pool.submit(job); } semaphore.acquire(10); semaphore.release(10); pool.shutdown(); }

Page 39: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 39

THREAD/THREADPOOL PERFORMANCE

public static void main(String[] args) throws Exception { ThreadConstructTest test = new ThreadConstructTest();

long time = System.currentTimeMillis(); test.noThreadPool(); System.out.println("No-Thread-Pool "+ (System.currentTimeMillis() - time)); time = System.currentTimeMillis(); test.fixedThreadPool(); System.out.println("Fixed-Thread-Pool "+ (System.currentTimeMillis() - time)); }}

Page 40: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 40

THREAD/THREADPOOL PERFORMANCE

OUTPUT PRODOTTO DALLA ESECUZIONE DEL PROGRAMMA:

No-Thread-Pool 11600Fixed-Thread-Pool 311

Page 41: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 41

ANCORA SULLA SERIALIZZAZIONE...

• JAVA offre una ampia scelta di strutture dati• dal punto di vista del programmatore, strutture dati diverse offrono

funzionalità simile, ma....è necessario capire come vengono implementate• ad esempio la serializzazione di strutture diverse può generare un

numero di bytes molto diverso...• esempio: Vector, ArrayList, LinkedList

– offrono funzionalità simili, ma sono implementate in modo diverso...– ArrayList: un puntatore ad un solo oggetto che cresce di dimensione

(il 50 % in più) mano a mano che si inseriscono elementi. Accesso diretto

– LinkedList: un puntatore all'inizio, uno alla fine e, per ogni elemento, un puntatore all'elemento successivo ed al precedente. Accesso sequenziale.

• Come si comportano se serializzati?

Page 42: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 42

ANCORA SULLA SERIALIZZAZIONE...

import java.util.*; import java.io.*;public class WritingSize {public static void test(List<String> list) throws IOException { insertJunk(list); for (int i = 0; i < 10; i++) list.add("hello world"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(list); out.close(); System.out.println(list.getClass().getSimpleName() + " used " + baos.toByteArray().length + " bytes"); }

Page 43: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 43

ANCORA SULLA SERIALIZZAZIONE...

private static void insertJunk(List<String> list) { for(int i = 0; i<1000 * 1000; i++) list.add("junk"); list.clear(); } public static void main(String[] args) throws IOException { test(new LinkedList<String>()); test(new ArrayList<String>()); test(new Vector<String>()); } }

Page 44: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 44

ANCORA SULLA SERIALIZZAZIONE...

OUTPUT PRODOTTO DALLA ESECUZIONE DEL PROGRAMMA:

LinkedList used 107 bytesArrayList used 117 bytesVector used 1310926 bytes

ArrayList 10 bytes in più per memorizzare la dimensione

Vector la clear non ha ridimensionato il vettore

Page 45: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 45

THREAD POOL: POLITICHE DI SATURAZIONE

• Politica di saturazione:– richiesta nel caso si utilizzino thread pool con code di dimensione

limitata– indica le azioni che devono essere effettuate nel caso in cui il pool è

saturo, cioè la coda è piena ed i threads del pool sono tutti attivi• Strategia di default: abort il task viene rifiutato e viene sollevata una

RejectedExecutionException • E' possibile definire una politica 'ad hoc' mediante un

Rejected Execution Handler• JAVA mette a disposizione diversi Rejected Execution Handler, ognuno

dei quali implementa una diversa politica di saturazione• Selezione della politica: setRejectedExecutionHandler

Page 46: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 46

THREAD POOL: POLITICHE DI SATURAZIONE

Politiche di saturazione: quando viene sottomesso un task T e la coda è piena,

possono essere adottate le seguenti politiche

• abort T viene scartato il task e viene sollevata un'eccezione

• discard rifiuta T, ma non solleva alcun tipo di eccezione

• discard oldest scarta il primo task della coda (quello che avrebbe dovuto essere eseguito successivamente) e inserisce T in coda

• caller-runs – non scarta il task e non solleva eccezioni. – cerca di rallentare (throttling, to throttle = strozzare) il flusso dei

tasks restituendo alcuni task al chiamante per l'esecuzione. – Il task non viene eseguito in un thread del pool, ma nel thread che ha

invocato la execute

Page 47: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 47

THREAD POOL: POLITICHE DI SATURAZIONE

import java.util.concurrent.*;public class prova{public static void main (String args[ ]){ThreadPoolExecutor executor=new

ThreadPoolExecutor(10,11,0L,TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(100));

executor.setRejectedExecutionHandler (new ThreadPoolExecutor.CallerRunsPolicy()); } }

Page 48: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 48

THREAD POOL: POLITICHE DI SATURAZIONE

• Consideriamo un Web Server – riceve richieste di servizio da parte dei clients– ogni richiesta corrisponde ad un diverso task

• Supponiamo che il Web Server definisca un thread pool che utilizzi una coda a dimensione limitata ed una politica di saturazione caller-runs.

• Se tutti i threads sono occupati e la coda è piena, il task successivo (la successiva richiesta di servizio) viene eseguita nel thread che ha invocato la execute (il main thread del server)

• Poiché l'esecuzione del servizio richiesto richiederà un intervallo di tempo ∆T, il main thread non sottometterà ulteriori taks per l'esecuzione al pool, durante ∆T

• Alcuni thread del pool possono terminare l'esecuzione del task assegnato durante ∆T, rendendosi disponibili a nuove sottomissioni

Page 49: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 49

THREAD POOL: POLITICHE DI SATURAZIONE

• Inoltre, il main thread, impiegato nell'esecuzione del task rifiutato dal pool, non accetta ulteriori connessioni (non esegue l'accept sul ServerSocket) durante l'intervallo di tempo ∆T

• Le richieste di servizio vengono quindi accodate a livello TCP

• Se l'overload persiste, sarà il livello TCP che eventualmente inizierà a scartare richieste, quando la sua coda sarà, a sua volta, satura

• Conclusione: se il server è sovraccarico, si può implementare una graceful degradation, spostando gradualmente il sovraccarico– dai thread del pool alla coda associata al pool, – dalla coda alla applicazione, – dall'applicazione al livello TCP – Il livello TCP è in grado di bloccare il client, mediante il meccanismo di

controllo del flusso

Page 50: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 50

POLITICHE DI SATURAZIONE: ESEMPI

public void process( ){ ThreadPoolExecutor exec = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue(0)); exec.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); while(true) {Object work = acquireWork(); if(work != null) exec.execute(new WorkerThread(work)); }}• supponiamo che 6 nuovi tasks vengano sottomessi a process, i primi 5 vengono

distribuiti ai worker threads, il sesto viene rifiutato ed eseguito da process• se tutti i tasks richiedono approssimativamente lo stesso tempo, tutti i

threads terminano l'esecuzione dei tasks approssimativamente nello stesso tempo

• se il sesto tasks richiede più tempo, il thread del pool rimangono inattivi

Page 51: Lezione n.11 LPR – Informatica Applicata Approfondimenti ...ricci/22-05-12-RMI-Miscellanea.pdfRMI, Threads Approfondimenti Laura Ricci 1 Università degli Studi di Pisa Dipartimento

Dipartimento di InformaticaUniversità degli Studi di Pisa

RMI, ThreadsApprofondimenti

Laura Ricci 51

POLITICHE DI SATURAZIONE: ESEMPI

public void process(){ ThreadPoolExecutor exec = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(5)); exec.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); while(true) {Object work = acquireWork(); if(work != null) {exec.execute(new WorkerThread(work)); }}}• Quando un task viene rifiutato, esistono alcuni task in coda

• Anche se process impiega molto tempo nella esecuzione del task rifiutato, esiste del lavoro extra che il therad pool distribuisce ai workers, mentre process elabora il task rifiutato