Procesare paralela in Java

Slides:



Advertisements
Similar presentations
Crearea unei prezentari PowerPoint
Advertisements

Politici publice Definirea problemelor Curs 3. Perceperea problemelor de politic ă public ă Problemele = nevoi umane care necesit ă rezolvare Problemele.
Synchronization in Java Nelson Padua-Perez Bill Pugh Department of Computer Science University of Maryland, College Park.
1 const #define DIMENSIUNE 1000 const int DIMENSIUNE = 1000; Utilizarea valorilor constante este importantă, de exemplu, în declararea tablourilor de date.
Present Perfect Continuous prezentare. schema Afirmativ: S + have/has + been + V-ing… Negativ: S + have/has + not + been + V-ing… Interogativ: have/has.
Multithreading in Java Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Acum câteva zile, când mă plimbam pe Strada Vieţii am observat un magazin pe care era scris: “ Magazinul Raiului ”.
1 Thread Pools. 2 What’s A Thread Pool? A programming technique which we will use. A collection of threads that are created once (e.g. when server starts).
CSS430 CPU Scheduling1 Textbook Ch5 These slides were compiled from the Applied OSC textbook slides (Silberschatz, Galvin, and Gagne) and the instructor’s.
Threads Concurrency in Java. What is mult-tasking? Doing more than one task.
Threads in Java. Processes and Threads Processes –A process has a self-contained execution environment. –Has complete set of runtime resources including.
1 (Worker Queues) cs What is a Thread Pool? A collection of threads that are created once (e.g. when a server starts) That is, no need to create.
Multithreading in Java Sameer Singh Chauhan Lecturer, I. T. Dept., SVIT, Vasad.
Multithreading / Concurrency
Thread Pools (Worker Queues) cs
Thread Pools (Worker Queues) cs
Chapter 5: CPU Scheduling
Februarie 2018 ASE Bucuresti
ACTIVITATEA 1 -,, PROFESOR IT LA PAPI’’
Funcţii Excel definite de utilizator (FDU) în VBA
Placa de bază.
Instrumente CASE Curs nr. 7.
Posibilităţi de analiză în timp real a parametrilor de calitate a apei cu ajutorul sistemului informatic de management SIVECO Business Analyzer September.
PASII INSTALARII SISTEMULUI DE OPERARE
Dispozitive de stocare
Arhitectura serviciilor web
Structura pipeline a unui procesor MIPS
Transport Layer Security TLS, SSL, HTTPS
Process management Information maintained by OS for process management
Paxos Made Simple Autor: Puşcaş Radu George
Primirea si procesarea cererilor
Retele de calculatoare
Reflexia luminii.
Cursul 3 Cautare peste siruri problema cautarea naiva
Software product management
CONVERSII INTRE SISTEME DE NUMERATIE
WebSite Social Tema 2 WebSite Social.
Sisteme de operare Răzvan Zota
Curs 2 1 Sistem de operare-concepte: 2 Apeluri de sistem
Curs 6: Introducere în programarea SAS
Programare și securitate la nivelul arhitecturii x86
Aplicatii client-server
Chapter 5: CPU Scheduling
Funcții C/C++ continuare
prof. mrd. Negrilescu Nicolae Colegiul National Vlaicu Voda
Ethernet.
Apache WEB Server.
Crearea si gazduirea serviciilor
Eclipsele de soare si de luna
Past Perfect Continuous
Forms (Formulare).
Chapter 5: CPU Scheduling
A great way to create a channel of communication
Functia de documentare
Administrarea reţelelor de calculatoare
Chapter 5: CPU Scheduling
SOAP -Simple Object Access Protocol-
Programarea in limbajul Java 2004 Lecturer: Gavrila Cristian
Planificarea proceselor
Software open source in industria software
Crearea unei aplicatii Windows Forms simple
Implementarea listelor simplu inlantuite
Harti de imagini, Cadre, Stiluri
Despre lamaie.net De ce sunt lamaile acre? Realizatori: Cristina Cazan
Java Based Techhnology
Outline Scheduling algorithms Multi-processor scheduling
Process Scheduling Decide which process should run and for how long
Shortest-Job-First (SJR) Scheduling
Java Chapter 3 (Estifanos Tilahun Mihret--Tech with Estif)
Chapter 5: CPU Scheduling
Presentation transcript:

Procesare paralela in Java 12/1/2017 Curs 8 Procesare paralela in Java

Arhitecturi Paralele

Clasificare arhitecturi paralele Clasificarea Flyn SISD - conventional SIMD - calcul vectorial MISD - scalcul sistolic MIMD – cazul general

SISD : Von Neuman Instructiuni Procesor Date Intrare Date Iesire

Arhitectura MISD B C A Flux de date de Iesire Flux de date de Intrare Instructiuni A Flux de date de Iesire Procesor A B C Instructiuni B Flux de Instructiuni C Flux de date de Intrare

Architectura SIMD Ci<= Ai * Bi A B C Flux de Instructiuni Flux de Procesor A B C Date de Intrare A Flux de Date de Iesire A Flux de Date de Iesire B Flux de Date de Intrare B Flux de Date de Iesire C Flux de Date de Intrare C Ci<= Ai * Bi

Architectura MIMD A B C Flux de Instructiuni A Flux de Instructiuni B Instructiuni C Flux de Date de Iesire A Flux de Date de Intrare A Procesor A Flux de Date de Iesire B Flux de Date de Intrare B Procesor B Flux de Date de Iesire C Flux de Date de Intrare C Procesor C

Masina MIMD cu memorie comuna Procesor A Procesor B Procesor C MEMORIE MAGISTRALA MEMORIE MAGISTRALA MEMORIE MAGISTRALA Sistem de Memorie Globala

MIMD cu memorie distribuita Canal Comunicatie Canal Comunicatie Procesor A Procesor B Procesor C MEMORIE MAGISTRALA MEMORIE MAGISTRALA MEMORIE MAGISTRALA Memorie Sistem A Memorie Sistem B Memorie Sistem C

Nivele de paralelism

Nivele de Paralelism Granularitate cod Entitate Cod Granularitate mare (nivel task) Program Granularitate medie (nivel control) Functie (thread) Granularitate fina (nivel date) Bucla Granularitate foarte fina (alegeri multiple ) Cu suport hard Task i-l Task i Task i+1 func1 ( ) { .... } func2 ( ) { .... } func3 ( ) { .... } a ( 0 ) =.. b ( 0 ) =.. a ( 1 )=.. b ( 1 )=.. a ( 2 )=.. b ( 2 )=.. + x Load

Paralelism la nivel de procese

Procesul clasic Memorie comuna Mentinuta de kernel procese processe Stiva Stiva Memorie COMUNA, segmente, pipes, Fisiere deschise sau mapate in memorie Date Date Text Text Memorie comuna Mentinuta de kernel procese processe

Definirea/Instantierea unor procese Exemple de relatii de precedenta

Procese cu unul sau mai multe fire interne de executie Proces cu un singur fir de executie Proces cu mai multe fire de executie Fire de executie Thread-uri Flux unic de instructiuni Spatiu de adrese COMUN pt fire Al procesului Flux multiplu de instructiuni

Thread-uri

Ce sunt firele de executie? Un fir de executie este o portiune de cod executabil care se poate executa in paralel (concurent) cu alte fire de executie) Registri Context Hardware/ software Cuvant stare Program Counter executare

Thread light (“proces usor”) STIVA FIRULUI Memorie Comuna DATELE FIRULUI TEXTUL FIRULUI Thread light (“proces usor”) Un fir de executie peste o zona mica continua de memorie care este primit de la (si din) procesul parinte

Exemplu Thread in Linux void *func ( ) { /* define local data */ - - - - - - - - - - - - - - - - - - - - - - /* function code */ thr_exit(exit_value); } main ( ) thread_t tid; int exit_value; thread_create (0, 0, func (), NULL, &tid); thread_join (tid, 0, &exit_value);

Paralelism in procese Date a b r1 c d r2 int add (int a, int b, int & result) // corpul int sub(int a, int b, int & result) Date Procesor a b r1 c d r2 IS1 add pthread t1, t2; pthread-create(&t1, add, a,b, & r1); pthread-create(&t2, sub, c,d, & r2); pthread-par (2, t1, t2); Processor IS2 sub

Paralelism date do “ dn/2 dn2/+1 dn sort( int *array, int count) //...... Procesor do “ dn/2 dn2/+1 dn Sortare pthread-t, thread1, thread2; “ pthread-create(& thread1, sort, array, N/2); pthread-create(& thread2, sort, array, N/2); pthread-par(2, thread1, thread2); IS Procesor Sortare

De ce thread-uri? Proces cu un singur fir de executie: apeluri blocante, executie secventiala Cu automat finit (bazat pe eveniment) apeluri neblocante si paralelism

Sistem de operare

Thread-uri utilizator 12/1/2017 Thread-uri utilizator Thread-urile sunt gestionate de o biblioteca de thread-uri

Thread-uri la nivel kernel 12/1/2017 Kernel-ul este constient de existenta thread-uri

Procese “usoare” (Light-weight-LWP) 12/1/2017 Procese “usoare” (Light-weight-LWP) Presupun maparea maparea mai multor LWP peste un proces real (greu - heavy-weight)

(UNIX, VMS, MVS, NT, OS/2 etc.) Sisteme Multitasking Proces Spatiu Utilizator Kernel Structura Procesului UNIX Hardware (UNIX, VMS, MVS, NT, OS/2 etc.)

Sisteme Multitasking Procese P1 P2 P3 P4 kernel Hardware Fiecare proces este independent kernel Hardware

Procese Multithread T1’s SP T3’sPC T1’sPC T2’sPC T1’s SP Cod Utilizator Date globale T2’s SP Structura Procesului Kernel

Maparea thread-urilor 1:1 DEC, NT, OS/1, AIX. IRIX M:1 HP-UNIX M:M 2-level

Modelul pe doua nivele al SunOS Proces Traditional Proc 1 Proc 2 Proc 3 Proc 4 Proc 5 Utilizator LWP-uri Thread-uri Kernel Kernel Hardware Procesoare

Paralelism la nivel de thread-uri

Multithreading – Mono procesor Concureta Vs Paralelism Concurenta P1 CPU P2 P3 timp

Multithreading - Multiprocesor Concurenta Vs Paralelism CPU P1 CPU P2 CPU P3 timp

Thread-uri la nivel user Model de lucru Thread-uri la nivel user Procesoare virtuale Procesoare fizice Planificare nivel user (User) Planificare nivel Kernel (Kernel)

Architectura generala a modelului bazat pe thread-uri Ascunde detaliile arhitecturii masinii Mapeaza thread-urile user peste cele native ale kernel Memoria procesului parinte este vazuta in comun de thread-uri

Modele de programare folosind thread-uri 1. master/slave Peer 3. pipeline

Modelul master slave Resurse Program sclavi Fisiere Baze Date Stapan taskX Baze Date Stapan taskY main ( ) Input (Stream) Disc-uri taskZ Dispozitive Speciale

Modelul peer Resurse Input (static) Program Sclavi Fisiere Baze Date 12/1/2017 Program Resurse Sclavi Input (static) Fisiere taskX Baze Date taskY Disc-uri taskZ Dispozitive Speciale

Pipeline de thread-uri Program Filtru Thread-uri Nivel 1 Nivel 2 Nivel 3 Input (Stream) Fisiere Baze date Disc-uri Dispozitive Speciale Fisiere Baze date Disc-uri Dispozitive Speciale Fisiere Baze date Disc-uri Dispozitive Speciale Resurse

Observatii privind utilizarea thread-urilor Daca toate operatiile sunt cu mai consumatoare de procesor nu este recomandat sa se lucreze pe thread-uri Desi crearea este simpla totusi foloseste ea insasi niste resurse Thread-urile prea simple (5 linii) nu sunt eficiente

Detalii fire de executie

Cai de creare a unui thread in Java class MyThread extends Thread { public void run() // corpul thread ce trebuie executat } MyThread thr1 = new MyThread(); thr1.start();

Se creaza o clasa care implementeaza interfata Runnable class ClassName implements Runnable { ..... public void run() // corpul thread ce trebuie executat } ClassName myObject = new ClassName(); Thread thr1 = new Thread( myObject ); thr1.start();

Exemplul 2 class ThreadDemo implements Runnable { ThreadDemo() {Thread ct = Thread.currentThread(); System.out.println("Current Thread: "+ct); Thread t = new Thread(this,"Demo Thread"); t.start(); try { Thread.sleep(3000); } catch(InterruptedException e) { System.out.println("Interrupted."); } System.out.println("Exiting mainthread."); }

public void run() { try { for(int i=5; i>0; i--) { System.out.println(" " + i); Thread.sleep(1000); } } catch(InterruptedException e) { System.out.println("Child interrupted."); } System.out.println("Exiting child thread."); public static void main(String args[]) new ThreadDemo();

Gestiunea thread-ului curent class CurrentThreadDemo { public static void main(String arg[]) { Thread ct = Thread.currentThread(); ct.setName( "My Thread" ); System.out.println("Current Thread : "+ct); try { for(int i=5; i>0; i--) { System.out.println(" " + i); Thread.sleep(1000); }

Current Thread : Thread[My Thread,5,main] catch(InterruptedException e) { System.out.println("Interrupted.") } Run: Current Thread : Thread[My Thread,5,main] 5 4 3 2 1

Ciclul de viata al unui thread

Runnable Thread-ul este lansat în execuţie prin apelul metodei start() din clasa Thread. Not Runnable - se poate ajunge în această stare dacă:

Dead În această stare se ajunge când firul şi-a terminat execuţia. Metoda isAlive() returnează: true, dacă firul de execuţie a fost pornit şi nu a fost oprit (este în starea Runnable sau Not Runnable) false, dacă firul de execuţie este fie în starea New Thread, fie în starea Dead.

Cazurile în care un fir de execuţie poate ajunge din starea Not Runnable în starea Runnable Dacă a fost apelată metoda sleep(), atunci firul execuţie ajunge în starea Runnable după scurgerea intervalului de timp specificat. Dacă a fost apelată metoda wait(), atunci un alt fir de execuţie trebuie să-l informeze dacă acea condiţie este îndeplinită sau nu (folosind metodele notify() şi notifyAll() din clasa Object).

Oprirea temporară a unui fir de execuţie public static void sleep(long millis) throws InterruptedException public static void sleep(long millis,int nanos) throws InterruptedException De exemplu: try { // se face o pauza de o secunda Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace();}

Terminarea unui fir de execuţie Pentru ca un fir de execuţie să se termine trebuie ca metoda run() să-şi termine execuţia. Există două metode pentru terminarea unui fir de execuţie: Metoda run() îşi termină execuţia în mod natural: dacă avem instrucţiuni cu timp de execuţie finit Daca avem bucle finite.

Fire de execuţie de tip „daemon” Un „daemon” reprezintă un fir de execuţie care se termină automat la terminarea aplicaţiei. De obicei firele „daemon” pun la dispoziţia celorlalte fire de execuţie anumite servicii.

Proceselor/firelor de executie Planificarea Proceselor/firelor de executie

Alternarea seventelor de calcul cu rafalele (“burst”) de instructiuni de intrare iesire

Planificatorul CPU Selecteaza dintre procesele active in memorie pe cele care sunt gata a fi executate si rezerva procesorul pentru unul din ele (secvential pur) Deciziile de planificare pot aparea atunci cand un proces: 1. Trece din starea de executie in starea de asteptare 2. Trece din starea de executie in starea de gata de executie 3. Trece din starea de asteptare in starea de gata de executie 4. Se termina

Distribuitorul/Selectorul de procese - Dispatcher Acest modul da controlul procesorului catre procesul selectat de catre planificatorul pe termen scurt si implica Schimbarea contextului Trecerea in mod utilizator Saltul catre locatia corespunzatoare din programul utilizatorului pentru a-l reporni Intarzierea selectorului – timpul necesar acestuia pentrua a opri un proces si a-l porni pe urmatorul

Criterii pentru realizarea planificarii Utilizarea procesor  Max Incarcare - Throughput –  Max Turnaround time – Min Timp de asteptare – Min Timp de raspuns – )  Min

Planificare de tip primul venit primul servit (FCFS) Proces Timp operatii i/o P1 24 P2 3 P3 3 Sa presupunem ca procesele ajung in urmatoarea ordine: P1 , P2 , P3 Atunci diagrama Gantt pentru planificare este: P1 P2 P3 24 27 30

FCFS Dca procesele ajung in ordinea P2 , P3 , P1 atunci vom avea urmatoarea diagrama Gatt a planificarii lor P1 P3 P2 6 3 30

Cea mai scurta sarcina este prima (SJF) Se asociaza fiecarui process lungimea urmatorului set de operatii de I/O care il va efectua (CPU burst). Aceste lungimi sunt folosite pentru a planifica procesul cu cel mai scurt timp Exista doua abordari: Nepreemptiva preemptiva

Exemplu de SJF nepreemptiv Proces Timp sosire Timp operatii I/O P1 0.0 7 P2 2.0 4 P3 4.0 1 P4 5.0 4 SJF (non-preemptiv) P1 P3 P2 7 3 16 P4 8 12

Exemplu de SJF preemptiv Proces Timp de aparitie Timp pentru i/o P1 0.0 7 P2 2.0 4 P3 4.0 1 P4 5.0 4 SJF (preemptiv) P1 P3 P2 4 2 11 P4 5 7 16

Planificare bazata pe prioritati Un numar al prioritatii este asociat la fiecare proces Procesorul va fi dat procesului cu prioritatea cea mai mare (adica cel mai mic numar). Si in acest caz procesul de planificare poate fi: Preemptiv nepreemptiv Problema  Starvation Solutie  Aging

Round Robin (RR) Fiecare proces primeste o mica unitate din timpul procesorului (cuanta de timp – time quantum), de obicei durata acesteia este intre 10 si 100 milliseconde. Daca exista n procese in aceasta coada si cuanta de timp este q, atunci fiecare proces va avea acces la 1/n din timpul procesorului in bucati de cel mult q unitati de timp o data. Rezulta ca nici un proces nu va astepta mai mult de (n-1)q unitati de timp. Performanta q este mare  FIFO q este mica  q trebuie sa fie mare tinand insa cont de comutarea contextului altfel supraincarcarea obtinuta va fi prea mare

Exemplu de RR cu cuanta de 20 Proces Timp pentru i/o P1 53 P2 17 P3 68 P4 24 Diagrama Gantt asociata va fi: P1 P2 P3 P4 20 37 57 77 97 117 121 134 154 162

Cuanta de timp si timpul de de comutare a contextului

Timpul de executie a unui proces variaza functie de cuanta de timp

Cozi multinivel Coada “gata de executie” este formata din doua cozi separate foreground – interactiva background – fundal (batch) Fiecare coada are propriul ei algoritm de planificare foreground – RR background – FCFS Planificarea trebuie realizata intre cozi Planificare cu prioritate fixa Cu cuante de timp

Planificarea cozilor multinivel

Coada de raspuns (feedback) multinivel Un proces poate fi mutat ntre cozi diferite (de exemplu “imbatranirea” poate fi implenentata in aceasta maniera Un planificator pentru coada de raspuns multinivel (multilevel-feedback-queue) este definit de utmatorii parametri Numarul cozilor Algoritmi de planificare pentru fiecare coada Metodele folosite pentru a determina cand se creste prioritatea unui proces Metodele folosite pentru a determina cand se scade prioritatea unui proces Metodele folosite pentru a determina in care coada va intra un proces care trebuie tratat

Exemplu de coada de raspuns multinivel Fie trei cozi: Q0 – cu cuanta de timp 8 milisecunde Q1 – cu cuanta de timp de 16 milisecunde Q2 – FCFS

Planificarea in Linux Se folosesc doi algoritmi Time-sharing Real-time Bazat pe prioritati de credit (Prioritized credit-based) – Creditul este scazut atunci cand apare o intrerupere de timp Cand creditul = 0, se alege alt proces Cand toate procesele au creditul = 0, se reincepe procesul de creditare Real-time Soft real-time Daca este conform standardului Posix.1b vom avea doua categorii FCFS si RR Procesul cu cea mai mare prioritate este primul executat

Planificarea thread-urilor Locala atunci cand ninlioteca de thread-uri va decide Globala atunci cand decide kernel-ul

Planificarea thread-urilor in Java JVM foloseste o politica de planificarea preemptiva bazata pe prioritati JVM va planifica un thread spre executare atunci cand: Thread-ul care este in executie curenta va parasi starea Runnable Un thread cu o prioritate mai mare intra in starea Runnable

Time-Slicing Deoarece planificarea pe cuante nu este asigurata de JVM trebuie folosita metoda yield() while (true) { // fa un calcul intensiv computational . . . Thread.yield(); }

Prioritatile thread-urilor Prioritate tip Thread.MIN_PRIORITY prioritate minima Thread.MAX_PRIORITY prioritate maxima Thread.NORM_PRIORITY prioritate implicita Prioritatile pot fi schimbate folosind metoda setPriority() De ex setPriority(Thread.NORM_PRIORITY + 2);

Exemplu Prioritati thread class Clicker implements Runnable { int click = 0; private Thread t; private boolean running = true; public Clicker(int p) { t = new Thread(this); t.setPriority(p); } public void run() { while(running) click++; } public void start() { t.start(); } public void stop() { running = false; }

Exemplu Prioritati thread class HiLoPri { public static void main(String args[]) {Thread.currentThread().setPriority(Thread.MAX_PRIORITY); Clicker Hi = new Clicker(Thread.NORM_PRIORITY+2); Clicker Lo = new Clicker(Thread.NORM_PRIORITY-2); Lo.start(); Hi.start(); try Thread.sleep(10000); } catch (Exception e) { }

Lo. stop(); Hi. stop(); System. out. println(Lo. click + " vs. " + Hi Lo.stop(); Hi.stop(); System.out.println(Lo.click + " vs. " + Hi.click); } Run1: (on Solaris) 0 vs. 956228 Run2: (Window 95) 304300 vs. 4066666

Problema inversiunii prioritatilor in cazul sincronizarii Fie un proces L de prioritate scazuta si un proces H de prioritate crescuta. Ambele au acces la o resursa comuna unica (adica se permite numai acces mutual exclusiv)

Solutia pentru inversia prioritatii Protocol de mostenire a prioritatilor Daca thread-ul t1 incearca sa achizitioneze un lock care este detinut de un thread de prioritate scazuta t2, atunci se va creste temporar prioritatea lui t2 la nivelul celei detinute de t1 in timpul in care t2 mentine lock-ul Protocol cu simularea limitarii prioritatii (Highest locker) Unui monitor I se da o prioritate atunci cand este creat. Aceasta este cea mai mare prioritate pe care un thread care incearca sa intre in zona monitorizata o poate avea O data ce thread-ul intra in zona sincronizata prioritatea lui este crescuta la cea a monitorului.

Coerenta datelor Ce facem daca mai multi vor sa scrie simultan aceasi valoare? Cea mai simpla solutie:excluziunea mutuala

Variabile pentru sincronizare in memoria comuna Proces 1 Proces 2 Variabila pentru sinchronizare Memorie Comuna S S S S Thread

Lock Definitie O entitate care poate fi detinuta de un singur thread la un moment dat Proprietati Reprezinta o forma/tip de sincronizare Este folosita pentru a intari/realiza excluziunea mutuala Thread-urile pot achizitiona/elibera un lock

Obiecte sincronizate in Java TOATE obiectele java furnizeaza (pt ca detin) un lock Se aplica cuvantul cheie synchronized asupra obiect Se obtine excluziunea mutuala pentru secventa din bloc Exemplu Object x = new Object(); void foo() { synchronized(x) { ... } bloc

Metode sincronizate in Java Si metodele Java furnizeaza lock-uri Se aplica cuvantul cheie synchronized la metoda Se sincronizeaza pe un obiect (implicit) apeland metoda Example synchronized void foo() { …cod… } // este echivalenta cu void foo() { synchronized (this) { …cod… } } bloc

Sincronizarea accesului la campuri “mutable” 12/1/2017 Sincronizarea accesului la campuri “mutable” Acestea sunt de fapt camputile care permit modificarea continutului. Intr-un mediu parallel ( multi thread) accesarea unei variabile commune necesita coordonare explicita intre cei care scri si cei care citesc datorita problemei coerentei datelor. Procesul de coordonare in acest caz se numeste sincronizare.

12/1/2017 Exemplu import java.util.Date; public final class MutablePlanet { public MutablePlanet(int aId, String aName, Date aDateOfDiscovery) fId = aId; fName = aName; fDateOfDiscovery = new Date(aDateOfDiscovery.getTime()); }

12/1/2017 public synchronized int getId() {return fId;} public synchronized void setId(int aNewId) { fId = aNewId; } public synchronized String getName() { return fName; } public synchronized void setName(String aNewName) { fName = aNewName; } public synchronized Date getDateOfDiscovery() { return new Date(fDateOfDiscovery.getTime()); } public synchronized void setDateOfDiscovery( Date aNewDiscoveryDate) { fDateOfDiscovery.setTime(aNewDiscoveryDate.getTime()); }

12/1/2017 private int fId; private String fName; private Date fDateOfDiscovery; // }

Indicatii pentru crearea unei clase imutabila 12/1/2017 Indicatii pentru crearea unei clase imutabila Asigurati ca clasa nu poate fi suprascrisa folosind final sau fabric static impreuna cu constructori private Campurile clasei trebuie sa fie private si final Nu furnizati nici o metoda care poate schimba starea unui obiect in nici un fel (nu nu mai setere si getere nimic)

Exemplu import java.util.Date; public final class Planet { 12/1/2017 Exemplu import java.util.Date; public final class Planet { public Planet (double aMass, String aName, Date aDateOfDiscovery) fMass = aMass; fName = aName; fDateOfDiscovery = new Date(aDateOfDiscovery.getTime()); }   public double getMass() { return fMass;

12/1/2017 public String getName() { return fName; } // public Date getDateOfDiscovery() { //not ok // return fDateOfDiscovery; // } public Date getDateOfDiscovery() {//ok return new Date(fDateOfDiscovery.getTime()); private final double fMass; private final String fName; private final Date fDateOfDiscovery;

12/1/2017 Lock In cazul lock-ului intrinsec operatiunea de lock va fi efectuata automat de catre Java (in spatele scenei). Utilizarea synchronized este asociata cu doua tipuri de lock intrinsec Un “lock pe instanta” care este atasat unui singur obiect Un “lock static” atasata unei clase

12/1/2017 In mod similar preluare controlului unui lock static va impedica celelalte thread-uri sa apeleze o metoda sincronizata static DANU NU va bloca apelul metodelor nesincronizate sau a instantelor de metoda sincronizate Lock-ul static poate fi obtinut in afara header-ului metodei in doua moduri synchronized(Blah.class),folosind clasa literal synchronized(this.getClass()), daca un obiect este disponibil

Exista doua categorii de operatii asupra unui obiect: Cu apel unic: Cu apel multiplu Exista mai multe situatii care trebuie analizate pentru a decide utilizarea lock-ului lock-never apelantul nu are nevoie nici o data sa obtina un lock extern inainte de a efectua orice tip de operatie.

lock-always – apelantul are nevoie intotdeauna sa obtina un lock extern inainte de efectuarea oricarei operatii. lock-sometimes – apelantul are nevoie cate o data sa obtina un lock extern inainte de a fectua unele operatii. Instantele sunt mutable iar implementarea clasei efectuare intern majoritatea sincronizarilor. lock-hostile – operatiile nu pot fi effectuate correct (safe) intr-un mediu multi-thread chiar daca se obtine tot tipul lock-ul extern.

Sincronizarea la nivel de sectiuni Controlul executiei

Hazard de curse - Data Race x = y = 0 Thread 1 Thread-urile pornesc Thread 2 x = 1 y = 1 j = y i = x Se poate sa avem ca rezultat i = 0 and j = 0?

Raspuns: DA! x = y = 0 Thread 1 Thread 2 Thread-urile pornesc x = 1 j = y i = x

Cum se poate intampla asa ceva? Compilatorul poate reordona instructiunile Sau sa mentina variabilele in registri Procesorul le poate reordona Modelul de memorie folosit este proiectat sa suporte otimizari agresive (cu relaxarea conditiilor) Poate include optimizari neimplementate in general

Sincronizarea Se foloseste cand Trebuie delimitat un bloc care trebuie sa aiba executie atomica (neintrerupta) de alt thread Introduce un punct de sincronizare a informatiei/comunicatiei intre thread-uri Obs Implica totusi o supraincarcare (mica) in timpul executiei.

Exemplu de operatiune neatomica public class OperNeAtomica implements Runnable { static int x = 0; public void run() { int tmp = x; x = tmp+1; } public static void main(String[] args) for (int i = 0; i < 3; i++) new Thread(new OperNeAtomica ()).start(); System.out.println(x); }

Probleme la sincronizare Utilizarea acelasi lock pentru a furniza excluderea mutuala Asigurarea tranzactiilor atomice Evitarea deadlock=ului

Utilizarea acelasi lock Lock comun Lock separat Exemplu void run() { Object o = new Object(); // diferit pentru fiecare thread synchronized(o) { … // sunt sanse sa apara data race }

Tranzactie atomica Problema potentiala Exemplu synchronized(lock) { int tmp = x; x = tmp; }

Utillizarea sincronizarii public class OperNeAtomica implements Runnable { static int x = 0; static Object lock = new Object(); public void run() { int tmp; synchronized(lock) { tmp = x; }; synchronized(lock) { x = tmp+1; } }

Evitarea blocajului reciproc In general este bine a se evita executia unor operatii consumatoare de timp intr-o zona de lock (cand se mentine controlul acestuia) Ce poate dura? Diverse… Aparitia altui lock Poate aparea blocaj reciproc (deadlock)

Exemplu Deadlock Thread1() { synchronized(a) synchronized(b) … ceva }

Exemplul 2 de deadlock void moveMoney(Account a, Account b, int amount) {synchronized(a) {synchronized(b) { a.debit(amount); b.credit(amount); } Thread1() { moveMoney(a,b,10); } Thread2() { moveMoney(b,a,100); }

Abstract Data Type – Buffer

Implementare Buffer public class Buffer { private LinkedList objects = new LinkedList(); public synchronized add( Object x ) { objects.add(x); } public synchronized Object remove() { while (objects.isEmpty()) { ; return objects.removeFirst();

Eliminare Deadlock public class Buffer { private Object [] myObjects; private int numberObjects = 0; public synchronized add( Object x ) { objects.add(x); } public Object remove() { while (true) { synchronize(this) { if (!objects.isEmpty()) { return objects.removeFirst(); } }

Metodele Wait & Notify wait() Apelata de un obiect notifyAll()

Utilizarea Wait si NotifyAll public class Buffer { private LinkedList objects = new LinkedList(); public synchronized add( Object x ) { objects.add(x); this.notifyAll(); } public synchronized Object remove() { while (objects.isEmpty()) { this.wait(); } return objects.removeFirst();

Codul devine public class Buffer { private LinkedList objects = new LinkedList(); public synchronized add( Object x ) {objects.add(x); this.notifyAll(); } public synchronized Object remove() { while (objects.isEmpty()) { try { this.wait(); } catch (InterruptedException e) {} } return objects.removeFirst();

Ce este un thread pool O colectie de thread-uri care sunt create simultan ( de exemplu cand un server porneste) NU este necesar ca serverul sa reeze cate un thread pe masura ce cererile de la clienti apar IN loc serverul poate folosi un thread care a fost deja creat si care fie este liber fie se va elibera in curand

De ce avem nevoie de thread pools Imbunatatesc utilizarea resurselor atentie crearea unui nou thread induce totusi o suprancarcare care nu poate neglijata Folosirea lor permite aplicatiilor sa isi controleze complet utilizarea thread-urilor interne

Utilizarea in servere Thread pools sunt importante in psecial pentru aplicatiile de tip client server Deoarece procesarea fiecarui task individual dureaza putin iasr numarul de cereri este mare Serverele nu trebuie sa consume mai mult timp si resurse pentru crearea si distrugerea thread-urilor decat pentru deservirea clientilor

Implementarea evidenta 12/1/2017 Implementarea evidenta Fie un pool de thread Fiecare task cere la pornire un thread si il returneaza pool-ului dupa ce si-a terminat treaba Care este problema aici Modelul “Synchronized” - clientul asteapta pana cand serverul ii satisface cererile

Implementarea evidenta …. nu e cea mai buna Cand pool-ul este gol threadu-l emitent de job trebuie sa astepte ca un thread sa fie disponibil De obicei se doreste evitarea blocarii acestui thread Un server ar putea dori sa efectueze unele actiuni cand vin prea multe cereri

Toate thread-urile worker asteapta pentru a primi treaba O solutie posibila Fiecare thread se uita dupa cereri (tasks) in coada wait() Coada Task-uri Thread-uri worker Daca Q este gol Toate thread-urile worker asteapta pentru a primi treaba

O solutie posibila Task Coada Task-uri Thread-uri worker Model “A-synchronized” “Lanseaza si uita ” Numarul de thread-uri worker este Fix. Atunci cand un task este introdus in coada Este apelat un notify

O solutie posibila Task Coada Task-uri Thread-uri Worker notify() Task Coada Task-uri Thread-uri Worker Numarul de thread-uri este fix Atunci cand un task este inserat In coada va fi apelat notify

Thread Pool Implementation public class TaskManager { LinkedList taskQueue = new LinkedList(); List threads = new LinkedList(); public TaskManager(int numThreads) {for(int i=0; i<numThreads; ++i) {Thread worker = new Worker(taskQueue); threads.add(worker); worker.start(); } public void execute(Runnable task) {synchronized(taskQueue) { taskQueue.addLast(task); taskQueue.notify(); }

Thread Pool Implementation public class Worker extends Thread { LinkedList taskQueue = null; public Worker(LinkedList queue) { taskQueue = queue; } public void run() { Runnable task = null; while (true) { synchronized (taskQueue) { while (taskQueue.isEmpty()) { try {taskQueue.wait();} catch (InterruptedException ignored) {} } task = (Runnable) taskQueue.removeFirst(); task.run();

Riscuri in folosirea Thread Pools Thread-urile pot avea scapari Sa se blocheze astepand terminarea unei operatii de i/o De exemplu clientul poate oprin interactiunea cu un socket fara a-l inchide corespunzator

Dimensiunea pool-ului Fiecare thread consuma resurse: memore, efort pentru management etc. Un pool mare poate conduce la infometare Task-urile care vin asteapta un thread liber

Tratarea a unui numar prea mare de cereri la un server multithtread Nu se adauga la coada de procesare toate cererile (se ignora sau se trimite un mesaj de eroare) Se folosesc cateva dimensiuni predefinite pentru pool conform tipului de incarcare al serverului ( dar ete bine ca sa nu schimbam prea des dimensiunea pool-ului)

Calculul dimensiunii pool Telul principale este: ca procesarea sa continue chiar daca se astepata ca operatii lente de I/O sa se termine Fie urmatoarele variabile: WT = timpul mediu estimat ST= timpul mediu de rezolvare estimat pentru o cerere (fara timpii de asteptare) Atunci: WT/ST+1 thread-uri vor fi de ajuns ca sa mentina procesorul la incarcare maxima

12/1/2017 Clasa Executor Are doua metode statice pentru crearea de pool-uri de thread-uri ExecutorService newFixedThreadPool(int nThreads) Poate crea un pool de dimensiune fixa ExecutorService newCachedThreadPool() Creaza noi thread-uri functie de necesitati Noile thread-uri sunt adaugate la pool si reciclate ExecutorService has an execute method void execute(Runnable command)

{ private final ServerSocket serverSocket; class NetworkService { private final ServerSocket serverSocket; private final ExecutorService pool; public NetworkService(int port, int poolSize) throws IOException { serverSocket = new ServerSocket(port); pool = Executors.newFixedThreadPool(poolSize); } public void serve() { try for (;;) { pool.execute(new Handler(serverSocket.accept()));} } catch (IOException ex) { pool.shutdown();

{ private final Socket socket; Handler(Socket socket) class Handler implements Runnable { private final Socket socket; Handler(Socket socket) { this.socket = socket; } public void run() { // citeste si deserveste cererea} }

Referinte https://www.cs.umd.edu/class/spring2006/cmsc132/ http://people.cs.uchicago.edu/~asiegel/courses/cspp51037/ http://www.cis.upenn.edu/~lee/01cis642/ http://users.ece.gatech.edu/~copeland/jac/3055-05/ http://www.buyya.com/ http://lass.cs.umass.edu/~shenoy/courses/spring05/ http://www.jguru.com/faq/view.jsp?EID=143462 http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html http://docs.oracle.com/javase/tutorial/essential/concurrency/exinter.html http://java2all.com/technology/core-java/multithreading/ thread-life-cycle

After …. this course